home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 February / EnigmA AMIGA RUN 15 (1997)(G.R. Edizioni)(IT)[!][issue 1997-02][PLANET CD V].iso / enigma / earcd / sviluppo / svilupp2 / amphn192.lha / src / amiphone.c next >
C/C++ Source or Header  |  1996-11-16  |  86KB  |  2,776 lines

  1. /* AmiPhone!  by Jeremy Friesner - jfriesne@ucsd.edu */
  2.  
  3. #define INTUI_V36_NAMES_ONLY
  4.  
  5. #include <stdio.h>
  6. #include <stdlib.h> 
  7. #include <string.h>
  8. #include <time.h>
  9.  
  10. #include <devices/timer.h>
  11. #include <devices/ahi.h>
  12. #include <dos/dos.h>
  13. #include <dos/dostags.h>
  14. #include <dos/dosextens.h>
  15. #include <intuition/intuition.h>
  16. #include <intuition/intuitionbase.h>
  17. #include <intuition/gadgetclass.h>
  18. #include <intuition/screens.h>
  19. #include <libraries/gadtools.h>
  20. #include <exec/ports.h>
  21. #include <exec/memory.h>
  22. #include <exec/types.h>
  23. #include <exec/tasks.h>
  24. #include <exec/io.h>
  25. #include <exec/libraries.h>
  26. #include <libraries/dos.h>            /* contains RETURN_OK, RETURN_WARN #def's */
  27. #include <graphics/gfxbase.h>
  28. #include <libraries/gadtools.h>
  29. #include <sys/types.h>
  30. #include <workbench/workbench.h>
  31. #include <workbench/startup.h>
  32. #include <resources/misc.h>
  33. #include <graphics/text.h>
  34.  
  35. #include <errno.h>
  36. #include <inetd.h>
  37.  
  38. #include <clib/alib_protos.h>
  39. #include <clib/dos_protos.h>
  40. #include <clib/exec_protos.h>
  41. #include <clib/intuition_protos.h>
  42. #include <clib/graphics_protos.h>
  43. #include <clib/gadtools_protos.h>
  44. #include <clib/wb_protos.h>
  45. #include <clib/icon_protos.h>
  46. #include <clib/diskfont_protos.h>
  47. #include <clib/iffparse_protos.h>
  48.  
  49. #include <pragmas/ahi_pragmas.h>
  50.  
  51. #include "toccata/include/libraries/toccata.h"
  52. #include "toccata/include/clib/toccata_protos.h"
  53. #include "toccata/include/pragmas/toccata_pragmas.h"
  54.  
  55. #include "phonerexx.h"
  56.  
  57. #include "menuconstants.h"
  58. #include "ciatimer.h"
  59. #include "phoneudp.h"
  60. #include "AmiPhone.h"
  61. #include "messages.h" 
  62. #include "AmiPhoneMsg.h"
  63. #include "AmiPhonePacket.h"
  64. #include "browse.h"
  65. #include "codec.h"
  66. #include "stringrequest.h"
  67. #include "TCPQueue.h"
  68. #include "delfph.h"
  69.  
  70. #define EWOULDBLOCK     35
  71.  
  72. #define IMAGE_QUIET    0
  73. #define IMAGE_XMIT1    1
  74. #define IMAGE_XMIT2    2
  75. #define IMAGE_XMIT3    3
  76. #define IMAGE_XMIT4    4
  77. #define IMAGE_NOCONN    5
  78. #define IMAGE_DISABLED    6
  79. #define IMAGE_TAPE      7
  80.  
  81. #define LEFT_SHIFT    0x60
  82. #define RIGHT_SHIFT    0x61
  83. #define SPACE_BAR    0x40
  84.  
  85. #define DOTSPACING 4
  86.  
  87. #define VSPACE    3
  88. #define HSPACE    3
  89.  
  90. /* defines */
  91. #define SLIDER_WIDTH    90
  92. #define MIC_OFFSET    5    /* offset from nearest window borders */
  93. #define MIC_DEPTH    2
  94. #define MIC_WIDTH    38
  95. #define MIC_HEIGHT    39
  96. #define MIC_ROWS    312
  97. #define MIC_LEFT    (MIC_OFFSET*2)
  98. #define MIC_BYTESPERROW 5 /* 38 + remaining bits, padded out to byte boundary of 40 */
  99. #define MIC_NUMFRAMES    8
  100. #define MIC_FRAMEWORDS  117                /* number of words/anim frame */
  101. #define MIC_PLANEWORDS  (MIC_FRAMEWORDS*MIC_NUMFRAMES)    /* Offset in ushorts to next bitplane */
  102. #define IsInMicButton(x,y) (((x)>=MIC_LEFT)&&((x)<(MIC_LEFT+MIC_WIDTH))&&((y)>=nMicTop)&&((y)<nMicTop+MIC_HEIGHT))
  103.  
  104. #define WID_TOP        (4+Scr->WBorTop+Scr->Font->ta_YSize)
  105. #define WIDLEFT     (MIC_WIDTH + MIC_OFFSET + 5)
  106. #define WIDWIDTH    17
  107. #define WIDHEIGHT     24
  108. #define WIDRECHEIGHT     14
  109.  
  110. #define VOLBARLEFT    (MIC_LEFT + MIC_WIDTH + 3)
  111. #define VOLBARTOP    (WID_TOP+1)
  112. #define VOLBARRIGHT    (VOLBARLEFT + 3)
  113.  
  114. #define WINDOWWIDTH     350
  115. #define WINDOWHEIGHT     (MIC_HEIGHT + MIC_OFFSET + WID_TOP)
  116.  
  117. #define MAXHEIGHT    (nRecGraphBottom-nRecGraphTop)
  118. #define HEIGHT144    (1440*MAXHEIGHT/(ulMaxBandwidth))
  119.  
  120.  
  121. #define GTIMERGO     SetTimer(GraphicTimerIO, 0, 500000)
  122.  
  123. /* Color codes for the scrolling graph */
  124. #define COLOR_SEND         7 
  125. #define COLOR_SEND_ERROR    2
  126. #define COLOR_RECEIVE       6
  127. #define COLOR_RECEIVE_ERROR 3
  128.  
  129. /* For key equivalents */
  130. #define SMALL_RATE_CHANGE 10
  131. #define LARGE_RATE_CHANGE 50
  132.  
  133. #define FIRST_CONNECT_TO    6
  134.  
  135. /* menus */
  136. struct NewMenu nmMenus[] = {
  137.     NM_TITLE, "Project",         NULL,  0L,         NULL, NULL,
  138.     NM_ITEM,  "About",            "?",  0L,         NULL, (void *) P_ABOUT,
  139.     NM_ITEM,  NM_BARLABEL,       NULL,  0L,         NULL, NULL,
  140.     NM_ITEM,  "Quit",             "Q",  0L,         NULL, (void *) P_QUIT,
  141.     NM_TITLE, "TCP",             NULL,  0L,        NULL, NULL,
  142.     NM_ITEM,  "Connect To",      NULL,  0L,         NULL, NULL,
  143.     NM_SUB,   "",             "1",  0L,       NULL, (void *) (T_CONNECTTO+0),
  144.     NM_SUB,   "",              "2",  0L,       NULL, (void *) (T_CONNECTTO+1),
  145.     NM_SUB,   "",             "3",  0L,       NULL, (void *) (T_CONNECTTO+2),
  146.     NM_SUB,   "",                 "4",  0L,       NULL, (void *) (T_CONNECTTO+3),
  147.     NM_SUB,   "",                 "5",  0L,       NULL, (void *) (T_CONNECTTO+4),
  148.     NM_SUB,   "",                 "6",  0L,       NULL, (void *) (T_CONNECTTO+5),
  149.     NM_SUB,   "",                 "7",  0L,       NULL, (void *) (T_CONNECTTO+6),
  150.     NM_SUB,   "",                 "8",  0L,       NULL, (void *) (T_CONNECTTO+7),
  151.     NM_SUB,   "",                 "9",  0L,       NULL, (void *) (T_CONNECTTO+8),
  152.     NM_SUB,   "",                 "0",  0L,       NULL, (void *) (T_CONNECTTO+9),
  153.     NM_ITEM,  "Connect",          "C",  0L,         NULL, (void *) T_CONNECT,
  154.     NM_ITEM,  "Disconnect",       "D",  0L,         NULL, (void *) T_DISCONNECT,
  155.     NM_ITEM,   "Show Daemon",     "S",  CHECKIT,    NULL, (void *) T_SHOWDAEMON,
  156.     NM_TITLE, "Messages",         NULL,  0L,         NULL, NULL,
  157.     NM_ITEM,  "Messages...",      "M",  0L,         NULL, (void *) M_MESSAGES,
  158.     NM_ITEM,  "Play Sound File",  "P",  0L,         NULL, (void *) M_PLAYFILE,
  159.     NM_ITEM,  "Record Memo",      "W",  CHECKIT,    NULL, (void *) M_RECORDMEMO,
  160.     NM_TITLE, "Settings",        NULL,  0L,         NULL, NULL,
  161.     NM_ITEM,  "Sampler",         NULL,  0L,         NULL, NULL,
  162.     NM_SUB,   "DSS8",         NULL,  CHECKIT,    NULL, (void *) S_DSS8,
  163.     NM_SUB,   "PerfectSound",    NULL,  CHECKIT,    NULL, (void *) S_PERFECTSOUND,
  164.     NM_SUB,   "AMAS",         NULL,  CHECKIT,    NULL, (void *) S_AMAS,
  165.     NM_SUB,   "Sound Magic",     NULL,  CHECKIT,    NULL, (void *) S_SOMAGIC,
  166.     NM_SUB,   "Toccata",         NULL,  CHECKIT,    NULL, (void *) S_TOCCATA,
  167.     NM_SUB,   "Aura PCMCIA",     NULL,  CHECKIT,    NULL, (void *) S_AURA,
  168.     NM_SUB,   "AHI Device",      NULL,  CHECKIT,    NULL, (void *) S_AHI,
  169.     NM_SUB,   "Delfina",         NULL,  CHECKIT,    NULL, (void *) S_DELFINA,
  170.     NM_SUB,   "Custom",         NULL,  CHECKIT,    NULL, (void *) S_CUSTOM,
  171.     NM_SUB,   "Generic",         NULL,  CHECKIT,    NULL, (void *) S_GENERIC,    
  172.     NM_ITEM,  "Compression",     NULL,  0L,            NULL, NULL,    
  173.     NM_SUB,   "ADPCM2",           "U",  CHECKIT,    NULL, (void *) S_ADPCM2,
  174.     NM_SUB,   "ADPCM3",           "I",  CHECKIT,    NULL, (void *) S_ADPCM3,
  175.     NM_SUB,   "None",             "O",  CHECKIT,    NULL, (void *) S_NOCOMP,
  176.     NM_ITEM,  "Transmit Enable", NULL,  0L,        NULL, NULL,    
  177.     NM_SUB,   "Toggle",           "T",  CHECKIT,    NULL, (void *) S_TOGGLE,
  178.     NM_SUB,   "Hold to Transmit", "H",  CHECKIT,    NULL, (void *) S_HOLD,
  179.     NM_ITEM,  "Line Gain",       NULL,  0L,        NULL, NULL,    
  180.     NM_SUB,   "Raise",            "]",  0L,        NULL, (void *) S_RAISELINEGAIN,
  181.     NM_SUB,   "Lower",            "[",  0L,        NULL, (void *) S_LOWERLINEGAIN,
  182.     NM_ITEM,  "Microphone Gain", NULL,  0L,        NULL, NULL,
  183.     NM_SUB,   "+20 dB",           "}",  CHECKIT,       NULL, (void *) S_TWENTYMICGAIN,
  184.     NM_SUB,   "+0 dB",            "{",  CHECKIT,       NULL, (void *) S_ZEROMICGAIN,    
  185.     NM_ITEM,  "Digital Amplify", NULL,  0L,         NULL, NULL,
  186.     NM_SUB,   "1X",                 NULL,  CHECKIT,    NULL, (void *) S_AMPONE,
  187.     NM_SUB,   "2X",                 NULL,  CHECKIT,    NULL, (void *) S_AMPTWO,
  188.     NM_SUB,   "4X",                 NULL,  CHECKIT,    NULL, (void *) S_AMPFOUR,
  189.     NM_ITEM,  "Input Channel",   NULL,  0L,        NULL, NULL,        
  190.     NM_SUB,   "Left",             "L",  CHECKIT,       NULL, (void *) S_LEFTCHANNEL,
  191.     NM_SUB,   "Right",            "R",  CHECKIT,       NULL, (void *) S_RIGHTCHANNEL,
  192.     NM_ITEM,  "Input Source",    NULL,  0L,        NULL, NULL,    
  193.     NM_SUB,   "Microphone",       "-",  CHECKIT,       NULL, (void *) S_INPUTMIC,
  194.     NM_SUB,   "Line",             "=",  CHECKIT,       NULL, (void *) S_INPUTEXT,
  195.     NM_ITEM,  "Enable on Connect","X",  CHECKIT,    NULL, (void *) S_ENABLEONCONN,
  196.     NM_ITEM,  "Xmit on Play",     "Y",  CHECKIT,    NULL, (void *) S_XMITONPLAY,
  197.     NM_ITEM,  "TCP Batch Xmit",   "B",  CHECKIT,    NULL, (void *) S_TCPBATCHXMIT,
  198.     NM_END,   NULL,             NULL,  NULL,       NULL, NULL
  199. };
  200.  
  201.  
  202. /* private functions */
  203. char * OpenLibraries(BOOL BOpen);
  204. static void SetPhoneEntry(int nNum, char * szCode);
  205. static void StopSoundPlayer(BOOL BNotifyUser);
  206. static void HandleSoundPort(BOOL BAllowNewPlayers);
  207. static BOOL AllocAHI(BOOL BAlloc);
  208. static void HandleAppWindow(void);
  209. static void GetSliderInfo(int * pnLabelWidth, int * pnValueWidth, int * pnHeight);
  210.  
  211. /* private functions */
  212. static UBYTE ParseBits(char * szString);
  213. static int CalcWindowHeight(int nFontHeight);
  214. static int CalcWindowWidth(int nLabelWidth, int nValueWidth);
  215.  
  216. /* private file-global data */
  217. static char [] = VERSION_STRING;
  218. static struct AmiPhoneInfo defMsg;
  219. static char szExitMessage[50] = "Error Initializing";
  220. static int ngExitVal = RETURN_ERROR;
  221. static int argc;
  222. static char ** argv;
  223. static struct DiskObject *AmiPhoneIconDiskObject = NULL;
  224. static char * szPhoneFileName = NULL;
  225. static char szWinTitle[130] = "";
  226. static struct Gadget *glist=NULL, *gad=NULL, *freqslider=NULL, *volslider=NULL, *delayslider=NULL;
  227. static struct NewGadget ng;
  228. static struct MsgPort * AppWindowPort = NULL;
  229. static struct AppWindow * AppWindow = NULL;
  230. static int nRecGraphTop, nRecGraphBottom, nRecGraphRight, nRecGraphLeft, nVolBarBottom;
  231. static BOOL BPropFont = FALSE;
  232.  
  233. /* global vars */
  234. struct AmiPhoneInfo * daemonInfo = &defMsg;        
  235.  
  236. /* AHI stuff? */
  237. struct Library    *AHIBase=NULL;
  238. struct MsgPort    *AHImp=NULL;
  239. struct AHIRequest *AHIio=NULL;
  240. BYTE               AHIDevice=-1;
  241.  
  242. char szVoiceMailDir[300] = "\0";
  243. FILE * fpMemo = NULL;
  244. void   *vi=NULL;
  245. const int Not[2] = {1,0};
  246. struct GfxBase * GfxBase       = NULL;
  247. struct Library * RexxSysBase   = NULL;
  248. struct Library * TimerBase     = NULL;
  249. struct Library * IntuitionBase = NULL;
  250. struct Library * SocketBase    = NULL;
  251. struct Library * GraphicsBase  = NULL;
  252. struct Library * GadToolsBase  = NULL;
  253. struct Library * IconBase      = NULL;
  254. struct Library * ToccataBase   = NULL;
  255. struct Library * WorkbenchBase = NULL;
  256. struct Library * DiskFontBase  = NULL;
  257. extern struct Library * DelfinaBase;
  258.  
  259. struct Library * MiscBase      = NULL;    /* this one not alloced with the others... */
  260.  
  261. struct Screen *Scr = NULL;
  262. struct Window *PhoneWindow = NULL;
  263. struct Menu * Menu = NULL;
  264. struct AmiPhoneGraphicsInfo GraphInfo;
  265. struct Process * GraphicDaemonProcess = NULL;
  266. struct RexxHost * rexxHost = NULL;
  267.  
  268. BOOL BNetConnect = FALSE, BTransmitting = FALSE, BStartedFromWB = FALSE, BSoundOn=FALSE;
  269. BOOL BGraphicsDaemon=FALSE, BButtonHeld = FALSE, BSpaceTapped = FALSE;
  270. BOOL BEnableOnConnect = FALSE, BXmitOnPlay = FALSE, BTCPBatchXmit = FALSE;
  271. BOOL BWasSamplingBefore = FALSE, BBrowserIsRunning = FALSE, BInvertSamples = FALSE;
  272. BOOL BUserDebug = FALSE;
  273.  
  274. struct BitMap MicBitMap;    /* For the kewl transmit button */
  275. int nAnimFrame=0;
  276.  
  277. ULONG ulDebug = 0L;
  278. ULONG ulBytesSentSince = 0L;
  279. ULONG ulTimerDelay = 0L;
  280. ULONG ulMilliSecondsTaken;
  281.  
  282. struct timerequest *GraphicTimerIO  = NULL;
  283. struct MsgPort       *GraphicTimerMP  = NULL;
  284. struct Message       *GraphicTimerMSG = NULL;
  285. struct Task * MainTask = NULL, *SoundPlayerTask = NULL, *FileReqTask = NULL;
  286. struct TextFont * fontdata = NULL;    /* The font's bits */
  287.  
  288. /* Here's where all data is compressed to and sent from */
  289. struct AmiPhoneSendBuffer    sendBuf;
  290. struct MsgPort *PhonePort = NULL, *SoundTaskPort = NULL;
  291.  
  292. /* Used to send playing messages */
  293. extern struct AmiPhonePacketHeader * TransferPacket;
  294.  
  295. /* user defaults */
  296. char szProgramName[30];
  297. static int nOldSendPri = 9999;    /* obviously invalid */
  298. UBYTE ubSamplerType = SAMPLER_GENERIC;
  299. char * pszCallNames[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
  300. char * pszCallIPs[]   = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
  301. int windowtop=-1, windowleft=-1, nSendPri = 999, nReceivePri = 1, nToggleMode = TOGGLE_TOGGLE, nSampleTechnique = TECHNIQUE_HARDINT;
  302. ULONG ulSampleArraySize; 
  303. ULONG ulKeyCode = 0L, ulRexxReceiveAve = 0L, ulRexxSendAve = 0L; 
  304. ULONG ulIdleRate = 500L;
  305. ULONG ulBytesPerSecond = 5600L, ulLastVolume, ulMaxBandwidth = 2880;
  306. float fPacketDelay = 0.2;    /* number of seconds between each packet */
  307. int nHackAmpVol = 1000;
  308. int nMinSampleVol = 7, nMaxSampleRate = DEFAULT_MAX_SAMPLE_RATE, nAmpShift = 0, nMaxDelay = MAX_PACKET_INTERVAL * 1000;
  309. UBYTE ubCurrComp = COMPRESS_ADPCM2, ubInputChannel = INPUT_JACK_LEFT, ubInputSource = INPUT_SOURCE_MIC;
  310. UBYTE ubCustStart=0, ubCustStop=0, ubCustLeft=0, ubCustRight=0, ubCustMic=0, ubCustExt=0, ubCustDir=SAMPBIT_SELSET | SAMPBIT_POUTSET | SAMPBIT_BUSYSET;
  311. UBYTE * pubCustSampleAt = NULL;
  312. BOOL BZoomed = FALSE, BProgramDone = FALSE;
  313. int nFontSize = 0, nMicTop = 0, nPostSendLen = 1, nPreSendQLen = 0;    /* 0 = default */
  314. char szFont[100]            = "";
  315. char szPubScreenName[100]         = "";
  316. char szPeerName[MAXPEERNAMELENGTH]      = "";
  317.  
  318. const char szSliderLabel1[] = "Sampling Rate";
  319. const char szSliderLabel2[] = "Transmit Delay";
  320. const char szSliderLabel3[] = "Silence Filter";
  321.  
  322. const char szSliderValue1[] = "88888Hz";
  323. const char szSliderValue2[] = "999ms";
  324. const char szSliderValue3[] = "88%";
  325.  
  326. /* external data */
  327. extern struct IntInfo IntData;
  328. extern BYTE sighalf, sigfull;
  329. extern __chip unsigned short microphone_image[];
  330. extern UBYTE * pubAllocedArray, * pubRightBuffer;
  331. extern struct AmiPhonePacketHeader * TransmitPacket[2];
  332. extern LONG sTCPSocket;
  333. extern char szLastMemoFile[200] = "(unset)";
  334. extern int delfsig, nMicGainValue;
  335.  
  336. /* Data to use after we get a CTRL-F from the Toccata Capture interrupt */
  337. extern UBYTE * pubBulkSamplePacket;
  338. extern ULONG ulBulkSamplePacketSum;
  339.  
  340. void debug(int nSec)
  341. {
  342.     printf("Waiting at debug point: [%i]\n",nSec);
  343.     Delay(20);
  344. }
  345.  
  346. void GraphicUpdate(ULONG ulSignals)
  347. {
  348.     if (GraphicDaemonProcess) 
  349.     {
  350.         Forbid(); GraphInfo.ubCommand |= ulSignals; Permit();
  351.         Signal((struct Task *)GraphicDaemonProcess,SIGBREAKF_CTRL_F);
  352.     }
  353. }
  354.  
  355. BOOL UsesInvertedSamples(void)
  356. {
  357.     BOOL BResult = (ubSamplerType == SAMPLER_GVPDSS8);
  358.     
  359.     if (BInvertSamples) BResult = Not[BResult];    
  360.     return(BResult);
  361. }
  362.  
  363. BOOL UsesCIAInterrupt(void)
  364. {
  365.     return((ubSamplerType != SAMPLER_DELFINA) &&
  366.            (ubSamplerType != SAMPLER_AHI) &&
  367.            (ubSamplerType != SAMPLER_TOCCATA));
  368. }
  369.  
  370. BOOL CanAmplify(void)
  371. {
  372.     return(TRUE);
  373. }
  374.  
  375. BOOL CanAdjustLineGain(void)
  376. {
  377.     return((ubSamplerType == SAMPLER_PERFECT) ||
  378.            (ubSamplerType == SAMPLER_TOCCATA) ||
  379.            (ubSamplerType == SAMPLER_DELFINA) ||
  380.            (ubSamplerType == SAMPLER_GVPDSS8));
  381. }
  382.  
  383. BOOL CanAdjustMicGain(void)
  384. {
  385.     return((ubSamplerType == SAMPLER_TOCCATA) ||
  386.            (ubSamplerType == SAMPLER_DELFINA));
  387. }
  388.  
  389. BOOL CanAdjustInputSource(void)
  390. {
  391.     return((ubSamplerType == SAMPLER_SOMAGIC) ||
  392.            (ubSamplerType == SAMPLER_CUSTOM)  ||
  393.            (ubSamplerType == SAMPLER_DELFINA) ||
  394.            (ubSamplerType == SAMPLER_TOCCATA));
  395. }
  396.  
  397.  
  398. BOOL CanAdjustInputChannel(void)
  399. {
  400.     return(ubSamplerType != SAMPLER_TOCCATA);
  401. }
  402.  
  403.  
  404.  
  405. BOOL AllocSliders(BOOL BAlloc)
  406. {    
  407.     if (BAlloc == TRUE)
  408.     {        
  409.         static struct TextAttr font;
  410.         static char szLevelString1[30],szLevelString2[30],szLevelString3[30];
  411.         int nLabelWidth, nValueWidth, nHeight, nSpacing;
  412.     
  413.         if (strlen(szFont) > 0) 
  414.         {
  415.             font.ta_Name  = szFont;
  416.             if (nFontSize == 0) font.ta_Flags |= FPF_DESIGNED;
  417.             font.ta_YSize = nFontSize;
  418.             
  419.             UNLESS(fontdata = OpenDiskFont(&font))
  420.             {
  421.                 printf("Warning: Couldn't load font %s/%i\n",szFont,nFontSize);
  422.                 AskFont(&Scr->RastPort, &font);
  423.             }
  424.         }
  425.         else AskFont(&Scr->RastPort, &font);
  426.  
  427.         BPropFont = ((font.ta_Flags & FPF_PROPORTIONAL) != 0);
  428.         
  429.         GetSliderInfo(&nLabelWidth, &nValueWidth, &nHeight);    
  430.         if (font.ta_YSize == 0) font.ta_YSize = nHeight;
  431.  
  432.         nSpacing = ((CalcWindowHeight(nHeight)-WID_TOP-Scr->WBorBottom-(nHeight*3))/3) + nHeight;
  433.         
  434.         UNLESS(vi = GetVisualInfo(Scr,TAG_END)) return(FALSE);
  435.         gad = CreateContext(&glist);
  436.  
  437.         /* setup sampling frequency slider */
  438.         ng.ng_TextAttr   = &font;
  439.         ng.ng_VisualInfo = vi;
  440.         ng.ng_GadgetText = szSliderLabel1;
  441.         ng.ng_LeftEdge   = MIC_LEFT+MIC_WIDTH+(VOLBARRIGHT-VOLBARLEFT)+(HSPACE*3)+nLabelWidth;
  442.         ng.ng_TopEdge    = WID_TOP;
  443.         ng.ng_Height     = nHeight;
  444.         ng.ng_Width      = SLIDER_WIDTH;
  445.         ng.ng_GadgetID   = FREQ_SLIDER;
  446.         ng.ng_Flags      = PLACETEXT_LEFT;
  447.         sprintf(szLevelString1,"%%%iluHz%s", 4+(nMaxSampleRate>=10000), BPropFont?"  ":"");        
  448.         freqslider = gad = CreateGadget(SLIDER_KIND, gad, &ng,
  449.             GTSL_Min,        (WORD)MIN_SAMPLE_RATE,
  450.             GTSL_Max,        (WORD)nMaxSampleRate,
  451.             GTSL_Level,        (WORD)ulBytesPerSecond,
  452.             GTSL_LevelFormat,     szLevelString1,
  453.             GTSL_LevelPlace,    PLACETEXT_RIGHT,
  454.             GTSL_MaxLevelLen,    7+(nMaxSampleRate >= 10000)+(BPropFont*2),
  455.             GA_RelVerify,        TRUE,
  456.             TAG_END);
  457.  
  458.  
  459.         /* setup send delay slider */
  460.         ng.ng_TopEdge    += nSpacing;
  461.         ng.ng_GadgetText = szSliderLabel2;
  462.         ng.ng_GadgetID   = DELAY_SLIDER;
  463.         sprintf(szLevelString2,"%%%ilums%s", 3, BPropFont?"  ":"");        
  464.         delayslider = gad = CreateGadget(SLIDER_KIND, gad, &ng,
  465.             GTSL_Min,        (WORD)(MIN_PACKET_INTERVAL*1000.0),    /* .09 seconds */
  466.             GTSL_Max,        (WORD)(nMaxDelay),    /* 700 mS or as specified by user */
  467.             GTSL_Level,        (WORD)(fPacketDelay*1000.0),        /* in milliseconds */
  468.             GTSL_LevelFormat,     szLevelString2,
  469.             GTSL_LevelPlace,    PLACETEXT_RIGHT,
  470.             GTSL_MaxLevelLen,    6+(BPropFont*2),
  471.             GA_RelVerify,        TRUE,
  472.             TAG_END);
  473.  
  474.         /* setup minimum volume slider */
  475.         ng.ng_TopEdge    += nSpacing;
  476.         ng.ng_GadgetText = szSliderLabel3;
  477.         ng.ng_GadgetID   = VOLUME_SLIDER;
  478.         sprintf(szLevelString3,"%%%ilu%%%%%s", 2, BPropFont?"  ":"");
  479.         volslider = gad = CreateGadget(SLIDER_KIND, gad, &ng,
  480.             GTSL_Min,        (WORD)0,
  481.             GTSL_Max,        (WORD)99,
  482.             GTSL_Level,        (WORD)nMinSampleVol,
  483.             GTSL_LevelFormat,     szLevelString3,
  484.             GTSL_LevelPlace,    PLACETEXT_RIGHT,
  485.             GTSL_MaxLevelLen,    4+(BPropFont*2),
  486.             GA_RelVerify,        TRUE,
  487.             TAG_END);
  488.     }
  489.     else
  490.     {
  491.         if (fontdata) {CloseFont(fontdata); fontdata = NULL;}
  492.         if (glist) {FreeGadgets(glist); glist = NULL;}
  493.         if (vi)    {FreeVisualInfo(vi); vi    = NULL;}
  494.     }    
  495.     return(TRUE);
  496. }
  497.  
  498.  
  499. void InitMicButton(void)
  500. {
  501.     int i;
  502.     
  503.     InitBitMap(&MicBitMap, MIC_DEPTH, MIC_WIDTH, MIC_ROWS);
  504.  
  505.     for (i=0;i<MicBitMap.Depth;i++)
  506.     {
  507.         MicBitMap.Planes[i]   = 
  508.             (PLANEPTR) µphone_image[i*MIC_PLANEWORDS];    
  509.     }
  510.     return;
  511. }
  512.  
  513. /* given a string, return the COMPRESS_MODE of it */
  514. UBYTE ParseCompMode(char * szParam)
  515. {
  516.     UpperCase(szParam);
  517.     
  518.     if (strcmp(szParam,"ADPCM2") == 0) return(COMPRESS_ADPCM2);
  519.     if (strcmp(szParam,"ADPCM3") == 0) return(COMPRESS_ADPCM3);
  520.     if (strcmp(szParam,"NONE")   == 0) return(COMPRESS_NONE);
  521.  
  522.     /* default */
  523.     return(COMPRESS_ADPCM2);
  524. }
  525.  
  526.  
  527.  
  528.  
  529. /* given a string, return the SAMPLER_TYPE of it */
  530. UBYTE ParseSamplerType(char * szParam)    
  531. {
  532.     UpperCase(szParam);
  533.     
  534.     /* The GVP DSS8 digitizer.  What I have :) */
  535.     if ((strncmp(szParam,"DSS",3) == 0)  ||
  536.         (strncmp(szParam,"GVP",3) == 0)) return(SAMPLER_GVPDSS8);
  537.  
  538.     /* The custom digitizer.  i.e. do whatever the user says to do */
  539.     if (strncmp(szParam,"CUSTOM",6) == 0) return(SAMPLER_CUSTOM);
  540.     
  541.     /* The Perfect Sound digitizer (no distinction currently made 
  542.        for different versions thereof) */
  543.     if (strncmp(szParam,"PERFECT",7) == 0) return(SAMPLER_PERFECT);
  544.         
  545.     /* The Tocatta 8/16 bit Zorro II based digitizer/sound card.  
  546.        For sampling only, in 8 bit mode.
  547.        Only recognize this ToolType if toccata.library is available. */
  548.     if ((ToccataBase)&&(strncmp(szParam,"TOC",3) == 0)) return(SAMPLER_TOCCATA);
  549.     
  550.     /* AMAS.  Untested.  */
  551.     if (strcmp(szParam,"AMAS") == 0)    return(SAMPLER_AMAS);
  552.     
  553.     /* Generic.  AmiPhone makes few assumptions about the digitizer.
  554.        This is the default.  */
  555.     if (strcmp(szParam,"GENERIC") == 0) return(SAMPLER_GENERIC);
  556.  
  557.     /* Sound magic. */
  558.     if (strncmp(szParam,"SO",2) == 0)   return(SAMPLER_SOMAGIC);
  559.  
  560.     /* Aura 12-bit PCMCIA. */
  561.     if (strcmp(szParam,"AURA") == 0)    return(SAMPLER_AURA);
  562.  
  563.     /* Delfina board. */
  564.     if ((DelfinaBase)&&(strcmp(szParam,"DELFINA") == 0)) return(SAMPLER_DELFINA);
  565.  
  566.     /* The AHI Device sound API */
  567.     if ((AHIBase)&&(strncmp(szParam,"AHI",3) == 0))  return(SAMPLER_AHI);
  568.         
  569.     /* default */
  570.     return(SAMPLER_GENERIC);
  571. }
  572.  
  573.  
  574. /* given a ubType, write the correct string into szWriteParam (max length: 20) */
  575. void GetSamplerType(char * szWriteParam, UBYTE ubType)    
  576. {
  577.     char * szType = "????";
  578.     
  579.     switch(ubType)
  580.     {
  581.         case SAMPLER_GVPDSS8:    szType = "GVPDSS8"; break;
  582.         case SAMPLER_CUSTOM:    szType = "CUSTOM";  break;
  583.         case SAMPLER_PERFECT:    szType = "PERFECTSOUND"; break;
  584.         case SAMPLER_TOCCATA:    szType = "TOCCATA"; break;
  585.         case SAMPLER_AMAS:    szType = "AMAS";    break;
  586.         case SAMPLER_GENERIC:    szType = "GENERIC"; break;
  587.         case SAMPLER_SOMAGIC:    szType = "SOUNDMAGIC"; break;
  588.         case SAMPLER_AURA:    szType = "AURA";    break;
  589.         case SAMPLER_DELFINA:    szType = "DELFINA"; break;
  590.         case SAMPLER_AHI:    szType = "AHI";        break;
  591.     }
  592.     Strncpy(szWriteParam, szType, 20);
  593. }
  594.  
  595. /* given a ubType, write the correct string into szWriteParam (max length: 20) */
  596. void GetSamplerState(char * szWriteParam)    
  597. {
  598.     char * szType = "????";
  599.     
  600.     switch(GraphInfo.nImageTop)
  601.     {
  602.         case IMAGE_QUIET: szType = "QUIET"; break;
  603.         
  604.         case IMAGE_NOCONN:szType = "NOCONN"; break;
  605.         
  606.         case IMAGE_DISABLED:szType = "DISABLED"; break;
  607.         
  608.         case IMAGE_XMIT1: case IMAGE_XMIT2: 
  609.         case IMAGE_XMIT3: case IMAGE_XMIT4:    
  610.         case IMAGE_TAPE:
  611.                   szType = "XMITTING"; 
  612.                   break;
  613.     }
  614.     Strncpy(szWriteParam, szType, 20);
  615. }
  616.  
  617.  
  618.  
  619. void DrawMicButton(int nOptImage)
  620. {
  621.     int nImage = 0;
  622.  
  623.     if (PhoneWindow == NULL) return;
  624.  
  625.     if (nOptImage >= 0) nImage = nOptImage;    /* override */
  626.     else
  627.     {
  628.         /* default logic */
  629.         if (BTransmitting == TRUE)     nImage = (nAnimFrame+1);
  630.         if (BSoundOn == FALSE)         nImage = IMAGE_QUIET;
  631.         if (BTransmitting == FALSE)    nImage = IMAGE_DISABLED;
  632.         if ((fpMemo == NULL)&&(BNetConnect == FALSE))     nImage = IMAGE_NOCONN;    
  633.         if ((SoundPlayerTask)&&(BXmitOnPlay)&&(BNetConnect)) nImage = IMAGE_TAPE;
  634.     }
  635.     GraphInfo.nImageTop = nImage;
  636.     GraphicUpdate(MSG_CONTROL_DOANIM);
  637. }
  638.  
  639.  
  640.  
  641.  
  642. void DrawHitBox(int nLeft, int nTop, int nRight, int nBottom, int nBackCol, BOOL BPressed)
  643. {
  644.     struct RastPort * rp = PhoneWindow->RPort;
  645.  
  646.     /* First draw the background color */
  647.     SetAPen(rp, nBackCol);
  648.  
  649.     RectFill(rp, nLeft, nTop, nRight, nBottom);
  650.         
  651.     /* Now draw the "press" lines */
  652.     if (BPressed == TRUE) SetAPen(rp, 1); /* black */
  653.              else SetAPen(rp, 2); /* white */
  654.              
  655.     /* Draw top press line */
  656.     Move(rp, nLeft+1, nTop);    Draw(rp, nRight-1, nTop);
  657.  
  658.     /* Draw left press line */
  659.     Move(rp, nLeft, nTop+1);     Draw(rp, nLeft, nBottom-1);
  660.     
  661.     if (BPressed == FALSE) SetAPen(rp, 1); /* black */
  662.               else SetAPen(rp, 2); /* white */
  663.     
  664.     /* Draw bottom press line */
  665.     Move(rp, nLeft+1, nBottom);    Draw(rp, nRight-1, nBottom);
  666.  
  667.     /* Draw right press line */
  668.     Move(rp, nRight, nTop+1);     Draw(rp, nRight, nBottom-1);
  669. }
  670.  
  671.  
  672.  
  673.  
  674.  
  675.  
  676. /* Code = CODE_ON, CODE_OFF, CODE_TOGGLE */
  677. void ToggleMicButton(int nCode)
  678. {
  679.     BOOL BOldState = BTransmitting;
  680.  
  681.     if (nCode == CODE_TOGGLE)
  682.     {
  683.         if (BOldState == TRUE)  nCode = CODE_OFF;
  684.         if (BOldState == FALSE) nCode = CODE_ON;
  685.     }
  686.     
  687.     /* Avoid donothing cases--just refresh the button is all */
  688.     if (((nCode == CODE_ON) &&(BTransmitting           == TRUE))  ||
  689.             ((nCode == CODE_ON) &&(SoundPlayerTask != NULL)&&(BXmitOnPlay == TRUE))  ||
  690.         ((nCode == CODE_OFF)&&(BTransmitting           == FALSE)) || 
  691.         ((BNetConnect == FALSE)&&(fpMemo == NULL)&&(nCode == CODE_ON)))
  692.     {
  693.         DrawMicButton(-1);
  694.         return;
  695.     }
  696.  
  697.     /* toggle the sampler */
  698.     BTransmitting = StartSampling(Not[BTransmitting], ulBytesPerSecond);
  699.  
  700.     /* If we're stopping the sound, tell the daemon to flush his buffer */
  701.     if ((nCode == CODE_OFF)&&(BNetConnect == TRUE)) SendCommandPacket(PHONECOMMAND_FLUSH,0,0L);
  702.     if (nCode == CODE_ON) BSoundOn = FALSE;    /* assume no sound until proven otherwise */
  703.     
  704.     if (BTransmitting != BOldState)
  705.     {
  706.         if (BTransmitting == TRUE) SetWindowTitle("Sampler Enabled.");
  707.                       else SetWindowTitle("Sampler Disabled.");
  708.     }
  709.     DrawMicButton(-1);
  710. }
  711.  
  712.  
  713.  
  714. void DisplayAbout(void)
  715. {    
  716.     char szMessage[300]="";
  717.     BOOL BWasOn = BTransmitting;
  718.     
  719.     if (BWasOn == TRUE) ToggleMicButton(CODE_OFF);
  720.     sprintf(szMessage,"AmiPhone v%i.%i%s\nby Jeremy Friesner\njfriesne@ucsd.edu\nCompiled: %s",
  721.                 VERSION_NUMBER/100, VERSION_NUMBER%100,
  722.                 #ifdef DEBUG_FLAG
  723.                 "D",
  724.                 #else
  725.                 "",
  726.                 #endif
  727.                 __DATE__);
  728.     MakeReq(NULL,szMessage,"Groovy");
  729.     if (BWasOn == TRUE) ToggleMicButton(CODE_ON);
  730.                 
  731. }
  732.  
  733.  
  734.  
  735.  
  736.  
  737. void UserError(char * message)
  738. {
  739.     MakeReq("AmiPhone Error", message, NULL);
  740. }
  741.  
  742.  
  743.  
  744. #define NUM_WEIGHTS 5
  745. void UpdateReceiveDisplays(void)
  746. {
  747.     static ULONG ulWeightsR[NUM_WEIGHTS], ulWeightsS[NUM_WEIGHTS];
  748.     static BYTE bNext = -1;
  749.     ULONG ulSizeR = daemonInfo->ulLastPacketSize, ulSizeS = ulBytesSentSince;
  750.     ULONG ulTotalR = 0L, ulTotalS = 0L, ulTemp;
  751.     
  752.     if (bNext == -1)
  753.     {
  754.         /* First time through here--initialize */
  755.         for (ulTemp=0;ulTemp<NUM_WEIGHTS;ulTemp++) 
  756.             ulWeightsR[ulTemp] = ulWeightsS[ulTemp] = 0L;
  757.     }
  758.     
  759.     bNext = (bNext + 1) % NUM_WEIGHTS;
  760.     ulWeightsR[bNext] = ulSizeR;
  761.     ulWeightsS[bNext] = ulSizeS;
  762.     
  763.     /* calculate averages */
  764.     for (ulTemp=0; ulTemp<NUM_WEIGHTS; ulTemp++) 
  765.     {
  766.         ulTotalR += ulWeightsR[ulTemp];
  767.         ulTotalS += ulWeightsS[ulTemp];
  768.     }
  769.  
  770.     ulRexxReceiveAve = ulTotalR/NUM_WEIGHTS << 1;
  771.     ulRexxSendAve    = ulTotalS/NUM_WEIGHTS << 1;
  772.  
  773.     Forbid(); 
  774.     GraphInfo.BErrorR     |= daemonInfo->BErrorR;
  775.     GraphInfo.nBarHeightR  = ulRexxReceiveAve * MAXHEIGHT / ulMaxBandwidth;
  776.     GraphInfo.nBarHeightS  = ulRexxSendAve    * MAXHEIGHT / ulMaxBandwidth + GraphInfo.nBarHeightR;
  777.     Permit();
  778.  
  779.     GraphicUpdate(MSG_CONTROL_DOGRAPH);
  780.  
  781.     /* Reset LastPacketSize, etc. */
  782.     daemonInfo->ulLastPacketSize = 0L;
  783.     daemonInfo->BErrorR         = FALSE;
  784.     ulBytesSentSince         = 0L;    
  785. }
  786.  
  787.  
  788.  
  789.  
  790.  
  791.  
  792.  
  793.  
  794. BOOL CreatePhoneMenus(BOOL BCreate)
  795. {   
  796.     void * VisualInfo = NULL;
  797.  
  798.     if (BCreate == FALSE) 
  799.     {
  800.         if (Menu) {FreeMenus(Menu); Menu = NULL;}
  801.         return(TRUE);
  802.     }
  803.  
  804.     /* Create menus */
  805.     UNLESS(Menu = CreateMenus(nmMenus, TAG_DONE))
  806.     {
  807.         UserError("Couldn't Create Menus!");
  808.         return(FALSE);
  809.     }
  810.     
  811.     UNLESS(VisualInfo = GetVisualInfo(Scr, TAG_END))
  812.     {
  813.         UserError("Couldn't get visual info for menus!");
  814.         return(FALSE);
  815.     }
  816.     
  817.     if (LayoutMenus(Menu, VisualInfo, TAG_DONE))
  818.     {
  819.         SetMenuStrip(PhoneWindow, Menu);
  820.     }
  821.     else
  822.     {
  823.         FreeVisualInfo(VisualInfo);
  824.         UserError("Couldn't LayoutMenus!");
  825.         return(FALSE);
  826.     }
  827.     FreeVisualInfo(VisualInfo);
  828.     return(TRUE);
  829. }
  830.  
  831.  
  832.  
  833. /* Custom set window title function */
  834. void SetWindowTitle(char * szOptNewMessage)
  835. {
  836.     static char szLastMessage[100] = "";
  837.     char szShortPeerName[11];
  838.     char szPacketString[11] = "";
  839.     char * pcTemp;
  840.     int nTCPQLenMS;
  841.     
  842.     if (szOptNewMessage) Strncpy(szLastMessage, szOptNewMessage, sizeof(szLastMessage));
  843.     
  844.     Strncpy(szShortPeerName, szPeerName, sizeof(szShortPeerName));
  845.     if (pcTemp = strchr(szShortPeerName,'.')) *pcTemp='\0';
  846.  
  847.     /* Estimate the milliseconds of audio in the queue! */
  848.     if (nTCPQLenMS = (1000*TCPQueueBytes(0))/ulBytesPerSecond)
  849.     {
  850.         switch(ubCurrComp)
  851.         {
  852.             case COMPRESS_ADPCM3:    nTCPQLenMS = nTCPQLenMS * 8 / 3;    break;
  853.             case COMPRESS_ADPCM2:    nTCPQLenMS *= 4;            break;
  854.         }
  855.         sprintf(szPacketString, "[%i.%is] ", nTCPQLenMS/1000, (nTCPQLenMS%1000)/100);
  856.     }
  857.     
  858.     sprintf(szWinTitle,"%s%s%s %s%s",
  859.         (BNetConnect ? "(" : ""),
  860.         (BNetConnect ? szShortPeerName : ""),
  861.         (BNetConnect ? ")" : ""),
  862.         szPacketString,
  863.         szLastMessage);
  864.  
  865.     if (PhoneWindow) 
  866.     {
  867.         /* Do this from the graphic update process if possible, to avoid blocking */
  868.         if (BGraphicsDaemon) GraphicUpdate(MSG_CONTROL_DOTITLE);
  869.                     else SetWindowTitles(PhoneWindow, szWinTitle, (char *) ~0);
  870.     }
  871. }
  872.  
  873.  
  874.  
  875.  
  876.     
  877.  
  878. void UpperCase(char *sOldString)
  879. {
  880.     char *i = sOldString;
  881.     const int diff = 'a' - 'A';
  882.  
  883.     UNLESS(sOldString) return();
  884.     
  885.     while (*i != '\0')
  886.     {
  887.             if ((*i >= 'a')&&(*i <= 'z')) *i = *i - diff;
  888.             i++;
  889.      }
  890.      return;
  891. }
  892.  
  893.  
  894. void LowerCase(char *sOldString)
  895. {
  896.     char *i = sOldString;
  897.     const int diff = 'a' - 'A';
  898.  
  899.     UNLESS(sOldString) return();
  900.     while (*i != '\0')
  901.      {
  902.             if ((*i >= 'A')&&(*i <= 'Z')) *i += diff;
  903.             i++;
  904.      }
  905.      return;
  906. }
  907.  
  908.  
  909. /* useful defines for menu controls */
  910. void SetMenuValues(void)
  911. {
  912.     struct Menu *currentMenu = Menu;
  913.     struct MenuItem *currentItem, *currentSub;
  914.     int i;
  915.     
  916.      UNLESS(currentMenu) return;
  917.      
  918.      DrawMicButton(-1);
  919.         
  920.     if (PhoneWindow) ClearMenuStrip(PhoneWindow);
  921.  
  922.     /* Project Menu */
  923.     /* Do Nothing for now */
  924.     
  925.     /* TCP Menu/Connect */
  926.     NEXTMENU; if (SocketBase) ENABLEMENU; else DISABLEMENU;
  927.     FIRSTITEM;if (BNetConnect) DISABLEITEM; else ENABLEITEM;
  928.     FIRSTSUB;
  929.     for (i=0;i<10;i++) 
  930.     {
  931.         if (pszCallIPs[i]) ENABLESUB; else DISABLESUB;
  932.         NEXTSUB;
  933.     }
  934.     NEXTITEM; if (BNetConnect) DISABLEITEM; else ENABLEITEM;
  935.  
  936.      NEXTITEM; if (BNetConnect) ENABLEITEM; else DISABLEITEM; 
  937.     NEXTITEM; if (daemonInfo->daemonTask) ENABLEITEM; else DISABLEITEM;
  938.           if (daemonInfo->BWindowIsOpen) CHECKITEM; else UNCHECKITEM;
  939.  
  940.     /* Messages Menu */
  941.     NEXTMENU;
  942.     FIRSTITEM; if ((strlen(szVoiceMailDir) == 0)||(BBrowserIsRunning)) DISABLEITEM; else ENABLEITEM;
  943.     NEXTITEM;  if (FileReqTask) DISABLEITEM; else ENABLEITEM;
  944.     NEXTITEM;  if (strlen(szVoiceMailDir) == 0) DISABLEITEM; else ENABLEITEM;
  945.            if (fpMemo != NULL) CHECKITEM; else UNCHECKITEM;
  946.     
  947.     /* Settings Menu/Sampler/DSS8 */
  948.     NEXTMENU; FIRSTITEM; 
  949.     FIRSTSUB; if (ubSamplerType == SAMPLER_GVPDSS8) CHECKSUB; else UNCHECKSUB;
  950.     NEXTSUB;  if (ubSamplerType == SAMPLER_PERFECT) CHECKSUB; else UNCHECKSUB;
  951.     NEXTSUB;  if (ubSamplerType == SAMPLER_AMAS)    CHECKSUB; else UNCHECKSUB;
  952.     NEXTSUB;  if (ubSamplerType == SAMPLER_SOMAGIC) CHECKSUB; else UNCHECKSUB;
  953.     NEXTSUB;  if (ToccataBase) 
  954.           {
  955.               ENABLESUB; 
  956.               if (ubSamplerType == SAMPLER_TOCCATA) CHECKSUB; else UNCHECKSUB;
  957.           }
  958.           else
  959.           {
  960.               DISABLESUB;
  961.               UNCHECKSUB;
  962.           }
  963.     NEXTSUB;  if (ubSamplerType == SAMPLER_AURA) CHECKSUB; else UNCHECKSUB;
  964.     NEXTSUB;  if (AHIBase)
  965.           {
  966.               ENABLESUB;
  967.               if (ubSamplerType == SAMPLER_AHI) CHECKSUB; else UNCHECKSUB;
  968.           }
  969.           else
  970.           {
  971.               DISABLESUB;
  972.               UNCHECKSUB;
  973.           }
  974.     NEXTSUB;  if (DelfinaBase)
  975.           {
  976.               ENABLESUB;
  977.               if (ubSamplerType == SAMPLER_DELFINA) CHECKSUB; else UNCHECKSUB;
  978.           }
  979.           else
  980.           {
  981.               DISABLESUB;
  982.               UNCHECKSUB;
  983.           }
  984.     NEXTSUB;  if (ubSamplerType == SAMPLER_CUSTOM)  CHECKSUB; else UNCHECKSUB;
  985.     NEXTSUB;  if (ubSamplerType == SAMPLER_GENERIC) CHECKSUB; else UNCHECKSUB;
  986.  
  987.     /* compression submenu */
  988.     NEXTITEM; 
  989.     FIRSTSUB; if (ubCurrComp == COMPRESS_ADPCM2) CHECKSUB; else UNCHECKSUB;
  990.     NEXTSUB;  if (ubCurrComp == COMPRESS_ADPCM3) CHECKSUB; else UNCHECKSUB;
  991.     NEXTSUB;  if (ubCurrComp == COMPRESS_NONE)   CHECKSUB; else UNCHECKSUB;
  992.  
  993.     /* Hold/toggle submenu */
  994.     NEXTITEM; 
  995.     FIRSTSUB; if (nToggleMode == TOGGLE_TOGGLE) CHECKSUB; else UNCHECKSUB;
  996.     NEXTSUB;  if (nToggleMode == TOGGLE_HOLD)   CHECKSUB; else UNCHECKSUB;
  997.  
  998.     /* Line Gain submenu */
  999.     NEXTITEM; if (CanAdjustLineGain()) ENABLEITEM; else DISABLEITEM;
  1000.     
  1001.     /* Mic Gain submenu */
  1002.     NEXTITEM; if (CanAdjustMicGain()) ENABLEITEM; else DISABLEITEM;
  1003.     FIRSTSUB; if (nMicGainValue == 20) CHECKSUB; else UNCHECKSUB;
  1004.     NEXTSUB;  if (nMicGainValue == 0)  CHECKSUB; else UNCHECKSUB;
  1005.  
  1006.     /* Amplify submenu */
  1007.     NEXTITEM; if (CanAmplify()) ENABLEITEM; else DISABLEITEM;
  1008.     FIRSTSUB; if (nAmpShift == 0) CHECKSUB; else UNCHECKSUB;
  1009.     NEXTSUB;  if (nAmpShift == 1) CHECKSUB; else UNCHECKSUB;
  1010.     NEXTSUB;  if (nAmpShift == 2) CHECKSUB; else UNCHECKSUB;
  1011.     
  1012.     /* Input channel submenu */
  1013.     NEXTITEM; if (CanAdjustInputChannel()) ENABLEITEM; else DISABLEITEM;
  1014.     FIRSTSUB; if (ubInputChannel == INPUT_JACK_LEFT)  CHECKSUB; else UNCHECKSUB;
  1015.     NEXTSUB;  if (ubInputChannel == INPUT_JACK_RIGHT) CHECKSUB; else UNCHECKSUB;
  1016.  
  1017.     /* Input source submenu */
  1018.     NEXTITEM; if (CanAdjustInputSource()) ENABLEITEM; else DISABLEITEM;
  1019.     FIRSTSUB; if (ubInputSource == INPUT_SOURCE_MIC) CHECKSUB; else UNCHECKSUB;
  1020.     NEXTSUB;  if (ubInputSource == INPUT_SOURCE_EXT) CHECKSUB; else UNCHECKSUB;
  1021.     
  1022.     /* Xmit on connect */
  1023.     NEXTITEM; if (BEnableOnConnect == FALSE)  UNCHECKITEM; else CHECKITEM;
  1024.               if (nToggleMode == TOGGLE_HOLD) DISABLEITEM; else ENABLEITEM;     
  1025.     
  1026.     /* Xmit on play */
  1027.     NEXTITEM; if (BXmitOnPlay == TRUE) CHECKITEM; else UNCHECKITEM;
  1028.  
  1029.     /* TCP Batch Xmit */
  1030.     NEXTITEM; if (BTCPBatchXmit == TRUE) CHECKITEM; else UNCHECKITEM;
  1031.         
  1032.     if (PhoneWindow) ResetMenuStrip(PhoneWindow,Menu);    
  1033.  
  1034.     /* If we are using a board that does not support volume
  1035.        detection, disable the volume threshold
  1036.        slider */
  1037.     GT_SetGadgetAttrs(volslider,PhoneWindow,NULL, GA_Disabled, 
  1038.                 Not[CanMeasureVolume()], TAG_END);
  1039. }
  1040.  
  1041.  
  1042. /* Tries to start recording if BStart is TRUE, else stops */
  1043. /* sets fpMemo */
  1044. BOOL StartRecording(BOOL BStart, char * szOptFileName)
  1045. {
  1046.     static time_t tStartTime;
  1047.     ULONG ulSecondsTaken = ulMilliSecondsTaken / 1000;
  1048.     
  1049.     if (BStart == (fpMemo != NULL)) return(FALSE);    /* is it already doing what we want? */
  1050.     if (BStart == TRUE)
  1051.     {
  1052.         tStartTime = time(NULL);
  1053.         if (fpMemo = szOptFileName ? fopen(szOptFileName,"wb")
  1054.                               : OpenMessageFile(tStartTime,szVoiceMailDir))
  1055.         {
  1056.             if (szOptFileName) Strncpy(szLastMemoFile, szOptFileName, sizeof(szLastMemoFile));
  1057.             ulMilliSecondsTaken = 0L;
  1058.             SetWindowTitle("Ready to record memo.");
  1059.             DrawMicButton(-1);
  1060.             return(TRUE);
  1061.         }
  1062.         SetWindowTitle("Error opening memo file.");
  1063.         return(FALSE);
  1064.     }
  1065.     else
  1066.     {
  1067.         BTransmitting = StartSampling(FALSE, ulBytesPerSecond);
  1068.         fclose(fpMemo);
  1069.         /* If no bytes were written, remove the file */
  1070.         UNLESS(ResetByteCounter()) RemoveMessageFile(tStartTime,szVoiceMailDir);
  1071.         fpMemo = NULL;
  1072.         if (ulSecondsTaken == 0L) ulSecondsTaken = 1L;
  1073.         SetMessageNote(tStartTime, "(Memo)", szVoiceMailDir, ulSecondsTaken);
  1074.         SetWindowTitle("Memo recording finished.");
  1075.         DrawMicButton(-1);
  1076.         return(TRUE);
  1077.     }
  1078. }
  1079.  
  1080. BOOL CanMeasureVolume(void)
  1081. {
  1082.     return(TRUE);
  1083. }
  1084.  
  1085.  
  1086. VOID wbmain(struct WBStartup *wbargv)
  1087. {
  1088.     BStartedFromWB = TRUE;
  1089.     main(0,(char **)wbargv);
  1090. }
  1091.  
  1092.  
  1093. BOOL FakeIDCMPMessage(ULONG class, ULONG code, ULONG qual)
  1094. {
  1095.     struct IntuiMessage fake;
  1096.     
  1097.     fake.Class      = class;
  1098.     fake.Code       = code;
  1099.     fake.Qualifier  = qual;
  1100.     
  1101.     return(HandleIDCMP(&fake));
  1102. }
  1103.  
  1104.  
  1105. void ChangeVolumeThreshold(int nNewPercentage)
  1106. {
  1107.     nMinSampleVol = nNewPercentage;      /* set the new volume to what the slider indicates */
  1108.     GT_SetGadgetAttrs(volslider, PhoneWindow, NULL, GTSL_Level, nMinSampleVol, TAG_END);
  1109.     IntData.ulThreshhold  = (nPreSendQLen == 0) ? ((nMinSampleVol*255)/100) : 0L;
  1110.     DrawMicButton(-1);
  1111. }
  1112.  
  1113.  
  1114.  
  1115. /* Handler for window events */
  1116. /* If fakeMessage is non-NULL, we'll use that as a parameter from our
  1117.    own code, and not reply it to Intuition */
  1118. BOOL HandleIDCMP(struct IntuiMessage * fakeMessage)
  1119. {
  1120.     struct IntuiMessage * message;
  1121.     ULONG class, code, qual, ulItemCode, ulNewFreq;
  1122.     struct MenuItem * mItem;
  1123.     struct Gadget * gad;
  1124.     static LONG lCode;
  1125.         
  1126.     /* Get the first message from the queue, or use the fake one if we have it*/
  1127.     message = fakeMessage ? fakeMessage : ((struct IntuiMessage *) GT_GetIMsg(PhoneWindow->UserPort));
  1128.  
  1129.     /* Examine pending messages */    
  1130.     while (message)
  1131.     {
  1132.         class = message->Class;        /* extract needed info from message */
  1133.         code  = message->Code;
  1134.         qual  = message->Qualifier;
  1135.         gad   = (struct Gadget *) message->IAddress;
  1136.  
  1137.         /* If the message came from Intuition, tell them we got it */
  1138.         if (message != fakeMessage) GT_ReplyIMsg(message);
  1139.  
  1140.         /* see what events occured, take correct action */
  1141.         switch(class)
  1142.         {    
  1143.             case IDCMP_MOUSEMOVE:
  1144.                 /* this is here because of the slider gadget--no need to do anything, though */
  1145.                 break;
  1146.                 
  1147.             case IDCMP_GADGETUP:
  1148.                 switch((message == fakeMessage) ? qual : gad->GadgetID)
  1149.                 {
  1150.                     case FREQ_SLIDER:
  1151.                         /* everything is done below for us! */
  1152.                         break;
  1153.                         
  1154.                     case DELAY_SLIDER:
  1155.                         fPacketDelay = ((float) code)/1000.0;    /* set new packet delay */
  1156.                         if (message == fakeMessage) GT_SetGadgetAttrs(delayslider, PhoneWindow, NULL, GTSL_Level, code, TAG_END);
  1157.                         code = ulBytesPerSecond;  /* make same as before */
  1158.                         break;
  1159.                         
  1160.                     case VOLUME_SLIDER:
  1161.                         ChangeVolumeThreshold(code);
  1162.                         code = ulBytesPerSecond;  /* make same as before */
  1163.                         break;
  1164.                 }
  1165.                 GT_SetGadgetAttrs(freqslider,PhoneWindow,NULL,GTSL_Level, 
  1166.                        ChangeSampleSpeed(code,ubCurrComp), TAG_END);
  1167.                 break;
  1168.  
  1169.             case IDCMP_NEWSIZE:
  1170.                 BZoomed = Not[BZoomed];
  1171.                 if (!BZoomed) 
  1172.                 {
  1173.                     DrawWindowBoxes();
  1174.                     GraphicUpdate(MSG_CONTROL_DOANIM | MSG_CONTROL_DOGRAPH);
  1175.                 }
  1176.                 break;
  1177.                 
  1178.             case IDCMP_REFRESHWINDOW:
  1179.                 GT_BeginRefresh(PhoneWindow);
  1180.                 GT_EndRefresh(PhoneWindow, TRUE);
  1181.                 break;
  1182.                     
  1183.             case IDCMP_CLOSEWINDOW: 
  1184.                 SetExitMessage("Window Closed",0);
  1185.                 BProgramDone = TRUE;  
  1186.                 break;
  1187.                 
  1188.             case IDCMP_VANILLAKEY:
  1189.                 if (code == ' ')
  1190.                 {
  1191.                          if (nToggleMode == TOGGLE_TOGGLE) ToggleMicButton(CODE_TOGGLE);
  1192.                     else if (nToggleMode == TOGGLE_HOLD)   
  1193.                     {
  1194.                         BSpaceTapped = TRUE;
  1195.                         BButtonHeld  = TRUE;
  1196.                         ToggleMicButton(CODE_ON);
  1197.                     }
  1198.                 }
  1199.                         
  1200.                 if ((code == 'e')||(code == 'E')) 
  1201.                 {
  1202.                     ToggleMicButton(CODE_ON);
  1203.                     if (nToggleMode == TOGGLE_HOLD)
  1204.                     {
  1205.                         BSpaceTapped = TRUE;
  1206.                         BButtonHeld = TRUE;
  1207.                     }
  1208.                 }
  1209.                 if ((code == 'd')||(code == 'D')) ToggleMicButton(CODE_OFF);
  1210.                 
  1211.                 if (ubSamplerType == SAMPLER_TOCCATA)
  1212.                 {
  1213.                     if ((code == '.')||(code == '>'))
  1214.                     {
  1215.                         ulNewFreq = ChangeSampleSpeed(T_NextFrequency(ulBytesPerSecond), ubCurrComp);
  1216.                         GT_SetGadgetAttrs(freqslider, PhoneWindow, NULL, GTSL_Level, ulNewFreq, TAG_END);    
  1217.                     }
  1218.                     if ((code == ',')||(code == '<'))
  1219.                     {
  1220.                          GT_SetGadgetAttrs(freqslider,PhoneWindow,NULL,
  1221.                                GTSL_Level, ChangeSampleSpeed(T_FindFrequency(0), ubCurrComp), TAG_END);    
  1222.                     }
  1223.                 }
  1224.                 else
  1225.                 {
  1226.                     if (code == ',') GT_SetGadgetAttrs(freqslider,PhoneWindow,NULL,
  1227.                                GTSL_Level, ChangeSampleSpeed(ulBytesPerSecond-SMALL_RATE_CHANGE, ubCurrComp), TAG_END);
  1228.                     if (code == '.') GT_SetGadgetAttrs(freqslider,PhoneWindow,NULL,
  1229.                                GTSL_Level, ChangeSampleSpeed(ulBytesPerSecond+SMALL_RATE_CHANGE, ubCurrComp), TAG_END);
  1230.                     if (code == '<') GT_SetGadgetAttrs(freqslider,PhoneWindow,NULL,
  1231.                                GTSL_Level, ChangeSampleSpeed(ulBytesPerSecond-LARGE_RATE_CHANGE, ubCurrComp), TAG_END);
  1232.                     if (code == '>') GT_SetGadgetAttrs(freqslider,PhoneWindow,NULL,
  1233.                                GTSL_Level, ChangeSampleSpeed(ulBytesPerSecond+LARGE_RATE_CHANGE, ubCurrComp), TAG_END);
  1234.                 }
  1235.                 break;
  1236.                 
  1237.             case IDCMP_MENUPICK:
  1238.                 while( code != MENUNULL ) 
  1239.                 {
  1240.                     if (message == fakeMessage)
  1241.                     {
  1242.                         ulItemCode = code;
  1243.                     }
  1244.                     else
  1245.                     {
  1246.                         mItem = ItemAddress( Menu, code );
  1247.                         ulItemCode = (ULONG) GTMENUITEM_USERDATA(mItem);
  1248.                     }
  1249.                     switch(ulItemCode)
  1250.                     {
  1251.                         case P_ABOUT:         DisplayAbout();                    break;
  1252.                         case P_QUIT:         SetExitMessage("You Quit",0); BProgramDone = TRUE; break;
  1253.                         case T_CONNECT:     DrawWindowBoxes(); ConnectPhoneSocket(TRUE,szPeerName); break;
  1254.                         case T_DISCONNECT:    SetWindowTitle("Connection closed."); ClosePhoneSocket(); break;
  1255.                         case T_SHOWDAEMON:    daemonInfo->BWantWindowOpen = Not[daemonInfo->BWindowIsOpen];  if (daemonInfo->daemonTask) Signal(daemonInfo->daemonTask,SIGBREAKF_CTRL_D); break;
  1256.                         case M_MESSAGES:    StartBrowser(szVoiceMailDir);         break;
  1257.                         case M_PLAYFILE:    FileReqTask = LaunchFileReq(szVoiceMailDir); break;
  1258.                         case M_RECORDMEMO:    StartRecording(fpMemo == NULL,NULL);break;
  1259.                         case S_DSS8:        ChangeSamplerType(SAMPLER_GVPDSS8); break;
  1260.                         case S_PERFECTSOUND:    ChangeSamplerType(SAMPLER_PERFECT); break;
  1261.                         case S_AMAS:        ChangeSamplerType(SAMPLER_AMAS);    break;
  1262.                         case S_TOCCATA:        ChangeSamplerType(SAMPLER_TOCCATA); break;
  1263.                         case S_CUSTOM:        ChangeSamplerType(SAMPLER_CUSTOM);  break;
  1264.                         case S_GENERIC:        ChangeSamplerType(SAMPLER_GENERIC); break;
  1265.                         case S_AURA:        ChangeSamplerType(SAMPLER_AURA);    break;
  1266.                         case S_AHI:        ChangeSamplerType(SAMPLER_AHI);     break;
  1267.                         case S_DELFINA:        ChangeSamplerType(SAMPLER_DELFINA); break;
  1268.                         case S_SOMAGIC:        ChangeSamplerType(SAMPLER_SOMAGIC); break;
  1269.                         case S_ADPCM2:        ChangeCompressMode(COMPRESS_ADPCM2);break;
  1270.                         case S_ADPCM3:        ChangeCompressMode(COMPRESS_ADPCM3);break;
  1271.                         case S_NOCOMP:        ChangeCompressMode(COMPRESS_NONE);  break;
  1272.                         case S_TOGGLE:        nToggleMode = TOGGLE_TOGGLE;    break;
  1273.                         case S_HOLD:        nToggleMode = TOGGLE_HOLD; ToggleMicButton(CODE_OFF); break;
  1274.                         case S_ENABLEONCONN:    BEnableOnConnect = Not[BEnableOnConnect];       break;
  1275.                         case S_XMITONPLAY:    BXmitOnPlay      = Not[BXmitOnPlay];       break;
  1276.                         case S_TCPBATCHXMIT:    BTCPBatchXmit    = Not[BTCPBatchXmit]; break;
  1277.                         case S_RAISELINEGAIN:    RaiseLineGain(1);             break;
  1278.                         case S_LOWERLINEGAIN:    RaiseLineGain(-1);                break;
  1279.                         case S_TWENTYMICGAIN:   SetMicGain(20);                 break;
  1280.                         case S_ZEROMICGAIN:    SetMicGain(0);                 break;
  1281.                         case S_AMPONE:        nAmpShift = 0; IntData.ulShiftLeft = 0L; break;
  1282.                         case S_AMPTWO:        nAmpShift = 1; IntData.ulShiftLeft = 1L; break;
  1283.                         case S_AMPFOUR:        nAmpShift = 2; IntData.ulShiftLeft = 2L; break;
  1284.                         case S_LEFTCHANNEL:    ChangeInputChannel(INPUT_JACK_LEFT); break;
  1285.                         case S_RIGHTCHANNEL:    ChangeInputChannel(INPUT_JACK_RIGHT); break;
  1286.                         case S_INPUTMIC:        ChangeInputSource(INPUT_SOURCE_MIC,TRUE); break;
  1287.                         case S_INPUTEXT:        ChangeInputSource(INPUT_SOURCE_EXT,TRUE); break;
  1288.                         default:         
  1289.                             if ((ulItemCode >= T_CONNECTTO)&&(ulItemCode <= T_CONNECTTO+9))
  1290.                             {
  1291.                                 DrawWindowBoxes(); 
  1292.                                 Strncpy(szPeerName,pszCallIPs[ulItemCode-T_CONNECTTO],MAXPEERNAMELENGTH);
  1293.                                 ConnectPhoneSocket(FALSE,szPeerName);
  1294.                             }
  1295.                             break;
  1296.                     }
  1297.                     code = (message == fakeMessage) ? MENUNULL : mItem->NextSelect;
  1298.                 }
  1299.                 SetMenuValues();
  1300.                 break;
  1301.                        
  1302.             case IDCMP_MOUSEBUTTONS:
  1303.                 if (code == SELECTDOWN)
  1304.                 {
  1305.                     if (IsInMicButton(message->MouseX,message->MouseY)) 
  1306.                     {
  1307.                         BButtonHeld = TRUE;
  1308.                         ToggleMicButton(CODE_TOGGLE);
  1309.                     }
  1310.                 }
  1311.                 else if ((code == SELECTUP)&&(nToggleMode == TOGGLE_HOLD))
  1312.                 {
  1313.                     BButtonHeld = FALSE;
  1314.                     ToggleMicButton(CODE_OFF);
  1315.                 }
  1316.                 break;
  1317.                 
  1318.             default:        printf("handleIDCMP: bad class\n");
  1319.                     break;
  1320.         }
  1321.     
  1322.         /* Only do the one message if it's a faked message */
  1323.         if (message == fakeMessage) return(BProgramDone);
  1324.  
  1325.         /* Get next message from the queue */
  1326.         message = (struct IntuiMessage *)GT_GetIMsg(PhoneWindow->UserPort);
  1327.     }
  1328.     return(BProgramDone);
  1329. }
  1330.  
  1331.     
  1332.  
  1333. /* Give param of TRUE to open libraries, param of FALSE to close */
  1334. /* returns NULL on success, name of unopened library on failure */
  1335. static char * OpenLibraries(BOOL BOpen)
  1336. {    
  1337.     if (BOpen == TRUE)
  1338.     {        
  1339.         /* Open critical libraries, or fail! */
  1340.         UNLESS(IntuitionBase = OpenLibrary("intuition.library",        37L)) return("intuition");
  1341.         UNLESS(GfxBase = GraphicsBase = OpenLibrary("graphics.library",37L)) return("graphics");
  1342.         UNLESS(GadToolsBase = OpenLibrary("gadtools.library",          36L)) return("gadtools");
  1343.         UNLESS(IconBase = OpenLibrary("icon.library",                  33L)) return("icon");
  1344.         UNLESS(DiskFontBase = OpenLibrary("diskfont.library",             37L)) return("diskfont");
  1345.  
  1346.         /* These libraries are optional--if they aren't opened, that's okay */
  1347.         WorkbenchBase = OpenLibrary("workbench.library",  37L);
  1348.         SocketBase    = OpenLibrary("bsdsocket.library",   2L);
  1349.         ToccataBase   = OpenLibrary("toccata.library",     6L);
  1350.         RexxSysBase   = OpenLibrary("rexxsyslib.library", 36L);
  1351.         
  1352.         InitDelfina();    /* On success of this function, DelfinaBase is set to non-NULL */
  1353.         
  1354.         AllocAHI(TRUE);
  1355.     }
  1356.     else
  1357.     {
  1358.         AllocAHI(FALSE);
  1359.         if (DelfinaBase)     CleanupDelfina();
  1360.         if (ToccataBase)     CloseLibrary(ToccataBase);
  1361.         if (WorkbenchBase)     CloseLibrary(WorkbenchBase);
  1362.         if (RexxSysBase)        CloseLibrary(RexxSysBase);
  1363.         if (IntuitionBase)      CloseLibrary(IntuitionBase);
  1364.         if (SocketBase)      CloseLibrary(SocketBase);
  1365.         if (GraphicsBase)      CloseLibrary(GraphicsBase);
  1366.         if (GadToolsBase)      CloseLibrary(GadToolsBase);
  1367.         if (DiskFontBase)     CloseLibrary(DiskFontBase);
  1368.         if (IconBase)          CloseLibrary(IconBase);
  1369.     }
  1370.     return(NULL);    /* NULL == success */
  1371. }
  1372.  
  1373.  
  1374.  
  1375.  
  1376.  
  1377. void SetExitMessage(char * message, int nExitVal)
  1378. {
  1379.     Strncpy(szExitMessage,message,sizeof(szExitMessage));
  1380.     ngExitVal = nExitVal;
  1381. }
  1382.  
  1383.  
  1384. BOOL StartSoundPlayer(char * szFileName)
  1385. {
  1386.     if (SoundPlayerTask = LaunchPlayer(szFileName))
  1387.     {
  1388.         BWasSamplingBefore = BTransmitting;
  1389.         if (BXmitOnPlay) ToggleMicButton(CODE_OFF);
  1390.         return(TRUE);
  1391.     }
  1392.     return(FALSE);
  1393. }
  1394.  
  1395.  
  1396. /* Don't return until the sound player has gone bye bye! */
  1397. static void StopSoundPlayer(BOOL BNotifyUser)
  1398. {
  1399.     UNLESS(SoundPlayerTask) return;
  1400.     
  1401.     if (BNotifyUser) SetWindowTitle("Closing SoundPlayer.");
  1402.  
  1403.     Signal(SoundPlayerTask, SIGBREAKF_CTRL_C);
  1404.  
  1405.     /* Stop any playing sounds! */
  1406.     while (SoundPlayerTask) 
  1407.     {
  1408.         WaitPort(SoundTaskPort);       
  1409.         HandleSoundPort(FALSE);
  1410.     }
  1411. }
  1412.  
  1413.  
  1414. void CleanExit(void)
  1415. {
  1416.     char szBuf[30];
  1417.     int nWaitIter=0,i;
  1418.     BOOL BAbortWait = FALSE;
  1419.     struct Message * SMessage;
  1420.     
  1421.     /* Stop recording any file we may be recording to */
  1422.     StartRecording(FALSE,NULL);
  1423.  
  1424.     /* Kill off our soundplayer port, and make sure the sound player won't hang waiting for us... */
  1425.     if (SoundTaskPort) 
  1426.     {
  1427.         /* Kill any playing sounds */
  1428.         StopSoundPlayer(TRUE);
  1429.     
  1430.         /* Kill the browser window */
  1431.         if (BBrowserIsRunning == TRUE)
  1432.         {
  1433.             SetWindowTitle("Closing Browser.");
  1434.             StopBrowser();            /* basically ctrl-c's it! */
  1435.             WaitPort(SoundTaskPort);    /* Wait for the ack */
  1436.             SMessage = GetMsg(SoundTaskPort);    /* Remove the ack */
  1437.             ReplyMsg((struct Message *)SMessage);    /* Let the guy continue */
  1438.         }
  1439.  
  1440.         /* If FileRequester is open, wait for it to be closed */
  1441.         while(FileReqTask)
  1442.         {
  1443.             SetWindowTitle("Please Close the File Requester!");
  1444.             WaitPort(SoundTaskPort);       
  1445.             HandleSoundPort(FALSE);
  1446.         }
  1447.     
  1448.         /* Get rid of SoundTaskPort! */
  1449.         Forbid();
  1450.         while(SMessage = GetMsg(SoundTaskPort)) ReplyMsg(SMessage);
  1451.         DeleteMsgPort(SoundTaskPort);
  1452.         SoundTaskPort = NULL;
  1453.         Permit();
  1454.     }        
  1455.     
  1456.     /* Tell server to exit */
  1457.     if (BNetConnect) ClosePhoneSocket();
  1458.     AddPhonePort(FALSE);
  1459.     
  1460.     /* Get rid of graphics daemon */
  1461.     if (BGraphicsDaemon)
  1462.     {
  1463.         SetWindowTitle("Closing Graphics Daemon.");
  1464.                 
  1465.         /* Wait for graphics daemon to respond */
  1466.         while(BGraphicsDaemon)
  1467.         {
  1468.             GraphicUpdate(MSG_CONTROL_BYE);
  1469.             Delay(1);
  1470.         }
  1471.     }
  1472.     SetWindowTitle("Shutting Down.");
  1473.  
  1474.         if (GraphicTimerIO != NULL)
  1475.         {
  1476.                 if (!(CheckIO((struct IORequest *)GraphicTimerIO))) 
  1477.                 {
  1478.                         AbortIO((struct IORequest *)GraphicTimerIO);   /* Ask device to abort any pending requests */
  1479.                         WaitIO((struct IORequest *)GraphicTimerIO);    /* proceed when ready */
  1480.                 }
  1481.                 CloseDevice((struct IORequest *) GraphicTimerIO);
  1482.                 DeleteExtIO((struct IORequest *) GraphicTimerIO);
  1483.     }
  1484.         if (GraphicTimerMP != NULL) DeletePort(GraphicTimerMP);
  1485.  
  1486.     if (PhonePort != NULL) 
  1487.     {    
  1488.         /* Reply any and all pending messages */
  1489.         Forbid();
  1490.         while (SMessage = GetMsg(PhonePort)) ReplyMsg(SMessage);
  1491.         DeleteMsgPort(PhonePort);
  1492.         Permit();
  1493.     }
  1494.  
  1495.     if (ngExitVal > RETURN_WARN)
  1496.     {
  1497.          printf("CleanExit: [%s] (exit code %i)\n", szExitMessage, ngExitVal);
  1498.          if (IntuitionBase)
  1499.          {
  1500.         sprintf(szBuf,"Exit (Code %i)", ngExitVal);
  1501.         MakeReq(NULL,szExitMessage, szBuf);
  1502.          }
  1503.     }
  1504.                 
  1505.     AllocSignals(FALSE);
  1506.     
  1507.      if (AppWindow) RemoveAppWindow(AppWindow);         
  1508.  
  1509.     /* throw out any leftover messages */
  1510.     if (AppWindowPort)
  1511.     {
  1512.         struct Message * amsg;
  1513.         
  1514.         Forbid();
  1515.         while(amsg = (struct AppMessage *) GetMsg(AppWindowPort)) ReplyMsg(amsg);
  1516.          Permit();
  1517.          DeleteMsgPort(AppWindowPort);
  1518.      }
  1519.      
  1520.     if (PhoneWindow) CloseWindow(PhoneWindow);
  1521.     
  1522.     CreatePhoneMenus(FALSE);        
  1523.     AllocSliders(FALSE);    
  1524.     if (Scr) UnlockPubScreen(NULL,Scr);
  1525.  
  1526.     /* If we changed our pri, reset to old one */
  1527.     if ((nOldSendPri < 128)&&(MainTask)) SetTaskPri(MainTask, nOldSendPri);
  1528.  
  1529.     /* Free all memory allocated for the Connect_To menu */
  1530.     for (i=0;i<10;i++)
  1531.     {
  1532.         if (pszCallNames[i]) FreeMem(pszCallNames[i],strlen(pszCallNames[i])+1);
  1533.         if (pszCallIPs[i])   FreeMem(pszCallIPs[i],  strlen(pszCallIPs[i])  +1);
  1534.  
  1535.     }
  1536.  
  1537.     SetupPreSendQueue(FALSE);    
  1538.     SetupTCPQueue(0,FALSE);
  1539.     
  1540.     if (rexxHost) CloseDownARexxHost(rexxHost);
  1541.  
  1542.     OpenLibraries(FALSE);        /* close all libraries */
  1543. }
  1544.  
  1545.  
  1546. LONG ChopValue(LONG ulVal, LONG ulLow, LONG ulHigh)
  1547. {
  1548.     if (ulVal < ulLow)  ulVal = ulLow;
  1549.     if (ulVal > ulHigh) ulVal = ulHigh;
  1550.     return(ulVal);
  1551. }
  1552.  
  1553.  
  1554. UBYTE ParseInputChannel(char * szParam)
  1555. {
  1556.     UpperCase(szParam);
  1557.     if (strcmp(szParam,"RIGHT") == 0) return(INPUT_JACK_RIGHT);
  1558.     if (strcmp(szParam,"LEFT")  == 0) return(INPUT_JACK_LEFT);
  1559.     
  1560.     /* default */
  1561.     return(INPUT_JACK_LEFT);
  1562. }
  1563.  
  1564.  
  1565. /* Sets all startup options from startup arguments, using ToolTypes if
  1566.    BStartedFromWB is TRUE, otherwise from command line */
  1567. void ParseArgs(BOOL BFromCLIButParseIconToo)
  1568. {
  1569.     int nParam,i;
  1570.     BOOL BSuccess;
  1571.     char *szParam = NULL, *pcTemp;
  1572.     static char szIconName[150];
  1573.     char szTemp[13];
  1574.     
  1575.     if ((BStartedFromWB)||(BFromCLIButParseIconToo))
  1576.     {
  1577.         if (BFromCLIButParseIconToo)
  1578.         {
  1579.             szPhoneFileName = argv[0];
  1580.             *szIconName = '\0';
  1581.  
  1582.             if ((szPhoneFileName == NULL)||(strlen(szPhoneFileName) == 0)||(strcmp(szPhoneFileName," ") == 0)) szPhoneFileName = "AmiPhone";
  1583.             
  1584.             /* Add path, if there isn't a base in the filename */
  1585.             pcTemp = strchr(szPhoneFileName,':');
  1586.             if (pcTemp == NULL) strcpy(szIconName,"PROGDIR:");        
  1587.  
  1588.             /* Add in executable name */
  1589.             strncat(szIconName, szPhoneFileName, sizeof(szIconName));
  1590.  
  1591.             szPhoneFileName = szIconName;            
  1592.         }
  1593.                 
  1594.         if (SetupToolTypeArg(szPhoneFileName) == FALSE) 
  1595.         {
  1596.                 szPhoneFileName = NULL;
  1597.                 if (BFromCLIButParseIconToo) ParseArgs(FALSE);
  1598.             return;
  1599.         }
  1600.  
  1601.     }    /* can't proceed unless we can access the icon! */
  1602.     else
  1603.     {
  1604.         /* Check to see if we want to autoconnect */
  1605.         if (argc > 1)
  1606.         {
  1607.             if ((IsKeyword(argv[1]) == FALSE)&&(SocketBase))
  1608.             {
  1609.                 /* autoconnect! */
  1610.                 Strncpy(szPeerName, argv[1], sizeof(szPeerName));
  1611.             }
  1612.         }
  1613.     }
  1614.     
  1615.     GetPhoneArg("TOP", &windowtop, &szParam);
  1616.     GetPhoneArg("LEFT", &windowleft, &szParam);
  1617.     
  1618.     /* Secret command line arg sent by AmiPhoned when it launches us! */
  1619.     if (GetPhoneArg("_KEY", &nParam, &szParam))
  1620.     {
  1621.         if (pcTemp = strchr(szParam,'|'))
  1622.         {
  1623.             *pcTemp = '\0';
  1624.             if (daemonInfo = ((struct AmiPhoneInfo *) atol(&pcTemp[1]))) daemonInfo->nPri = nReceivePri;
  1625.         }
  1626.         UNLESS(ulKeyCode = atol(szParam)) daemonInfo = NULL;
  1627.     }
  1628.     
  1629.     if (GetPhoneArg("SAMPLETECHNIQUE", &nParam, &szParam))         
  1630.     {
  1631.         UpperCase(szParam);
  1632.         if (strncmp(szParam,"SOFT",4) == 0)
  1633.         {
  1634.             nSampleTechnique  = TECHNIQUE_SOFTINT;  
  1635.             ulBytesPerSecond /= 2;
  1636.         }
  1637.         else if (strncmp(szParam,"HARD",4) == 0)
  1638.         {
  1639.             nSampleTechnique  = TECHNIQUE_HARDINT;
  1640.         }
  1641.     }
  1642.     
  1643.     /* Dont do autoconnect from tooltype if we started from CLI!  It's annoying */
  1644.     if ((SocketBase)&&(!BFromCLIButParseIconToo)&&(GetPhoneArg("CONNECT", &nParam, &szParam)))
  1645.                     Strncpy(szPeerName,szParam,sizeof(szPeerName));
  1646.                     
  1647.     if (GetPhoneArg("MAXBANDWIDTH", &nParam, &szParam))  ulMaxBandwidth = ChopValue(nParam,75,100000);
  1648.     if (GetPhoneArg("COMPRESS", &nParam, &szParam))      ubCurrComp     = ParseCompMode(szParam);
  1649.     
  1650.     if (GetPhoneArg("THRESHVOLUME", &nParam, &szParam))  nMinSampleVol  = ChopValue(nParam,0,99);
  1651.     if (GetPhoneArg("MINVOLUME", &nParam, &szParam))     nMinSampleVol  = ChopValue(nParam,0,99);
  1652.     
  1653.     if (GetPhoneArg("ENABLEONCONNECT", &nParam, &szParam)) BEnableOnConnect = TRUE;
  1654.     if (GetPhoneArg("XMITONCONNECT", &nParam, &szParam)) BEnableOnConnect = TRUE;
  1655.     if (GetPhoneArg("XMITONPLAY", &nParam, &szParam))    BXmitOnPlay      = TRUE;
  1656.     if (GetPhoneArg("TCPBATCHXMIT", &nParam, &szParam))  BTCPBatchXmit    = TRUE;
  1657.     if (GetPhoneArg("SENDPRI", &nParam, &szParam))       nSendPri         = ChopValue(nParam,-127,127);
  1658.     if (GetPhoneArg("RECEIVEPRI", &nParam, &szParam))    nReceivePri      = ChopValue(nParam,-127,127);
  1659.     if (GetPhoneArg("HOLDTOTRANSMIT", &nParam, &szParam))nToggleMode      = TOGGLE_HOLD;
  1660.     if (GetPhoneArg("MAXSAMPLERATE", &nParam, &szParam)) nMaxSampleRate   = ChopValue(nParam,MIN_SAMPLE_RATE,ABSOLUTE_MAX_SAMPLE_RATE);
  1661.     if (GetPhoneArg("SAMPLERATE", &nParam, &szParam))    ulBytesPerSecond = ChopValue(nParam,MIN_SAMPLE_RATE,nMaxSampleRate);
  1662.     if (GetPhoneArg("SAMPLER", &nParam, &szParam))       ubSamplerType    = ParseSamplerType(szParam);
  1663.     if (GetPhoneArg("INPUTCHANNEL", &nParam, &szParam))  ubInputChannel   = ParseInputChannel(szParam);
  1664.     if (GetPhoneArg("VOICEMAILDIR", &nParam, &szParam))  Strncpy(szVoiceMailDir,szParam,sizeof(szVoiceMailDir));
  1665.         if (GetPhoneArg("INPUTSOURCE",&nParam,&szParam))
  1666.         {
  1667.             if (*szParam == 'M') ubInputSource = INPUT_SOURCE_MIC;
  1668.             if (*szParam == 'L') ubInputSource = INPUT_SOURCE_EXT;
  1669.         }
  1670.         else if (ubSamplerType == SAMPLER_TOCCATA)
  1671.     {
  1672.         /* Try to get current input source setting from Toccata prefs */
  1673.         struct TagItem taglist[2];
  1674.         LONG lInputSource;
  1675.         
  1676.         taglist[0].ti_Tag = PAT_Input; taglist[0].ti_Data = &lInputSource;
  1677.         taglist[1].ti_Tag = TAG_DONE;  taglist[1].ti_Data = NULL;
  1678.         T_GetPart(taglist);
  1679.         ubInputSource = (lInputSource == TINPUT_Mic) ? INPUT_SOURCE_MIC : INPUT_SOURCE_EXT;
  1680.         }
  1681.         if (GetPhoneArg("AMPLIFY",&nParam,&szParam))
  1682.         {
  1683.             if (*szParam == '1') nAmpShift = 0;
  1684.             if (*szParam == '2') nAmpShift = 1;
  1685.             if (*szParam == '4') nAmpShift = 2;
  1686.         }
  1687.  
  1688.     BSuccess = GetPhoneArg("PUBSCREEN", &nParam, &szParam);
  1689.     if (!BSuccess) BSuccess = GetPhoneArg("PUBLICSCREEN", &nParam, &szParam);
  1690.     if (BSuccess) Strncpy(szPubScreenName,szParam,sizeof(szPubScreenName));
  1691.     
  1692.     if (GetPhoneArg("MAXXMITDELAY",&nParam,&szParam)) nMaxDelay = ChopValue(nParam,(MIN_PACKET_INTERVAL * 1000),999);
  1693.     if (GetPhoneArg("LINEGAIN",&nParam,&szParam)) RaiseLineGain(nParam);
  1694.     if (GetPhoneArg("MICGAIN",&nParam,&szParam)) SetMicGain(nParam ? 20 : 0);
  1695.     else if (ubSamplerType == SAMPLER_TOCCATA)
  1696.     {
  1697.         /* Try to get current gain settings from Toccata prefs */
  1698.         struct TagItem taglist[3];
  1699.         LONG lInputGain, lMicGain;
  1700.         
  1701.         taglist[0].ti_Tag = PAT_InputVolumeLeft; taglist[0].ti_Data = &lInputGain;
  1702.         taglist[1].ti_Tag = PAT_MicGain;     taglist[1].ti_Data = &lMicGain;
  1703.         taglist[2].ti_Tag = TAG_DONE;         taglist[2].ti_Data = NULL;
  1704.         T_GetPart(taglist);
  1705.         RaiseLineGain(lInputGain);
  1706.     }
  1707.     if (GetPhoneArg("IDLERATE",&nParam,&szParam)) ulIdleRate = ChopValue(nParam,1,ABSOLUTE_MAX_SAMPLE_RATE);
  1708.     if (GetPhoneArg("INVERTWAVEFORM",&nParam,&szParam)) BInvertSamples = TRUE;
  1709.     
  1710.     /* Custom digitizer control arguments */
  1711.     if (GetPhoneArg("PRESEND",     &nParam, &szParam)) nPreSendQLen = nParam;
  1712.     if (GetPhoneArg("POSTSEND",     &nParam, &szParam)) nPostSendLen = nParam;
  1713.     if (GetPhoneArg("CUSTSTARTBITS", &nParam, &szParam)) ubCustStart = ParseBits(szParam);
  1714.     if (GetPhoneArg("CUSTSTOPBITS",  &nParam, &szParam)) ubCustStop  = ParseBits(szParam);
  1715.     if (GetPhoneArg("CUSTDIRBITS",   &nParam, &szParam)) ubCustDir   = ParseBits(szParam);
  1716.     if (GetPhoneArg("CUSTLEFTBITS",  &nParam, &szParam)) ubCustLeft  = ParseBits(szParam);
  1717.     if (GetPhoneArg("CUSTRIGHTBITS", &nParam, &szParam)) ubCustRight = ParseBits(szParam);
  1718.     if (GetPhoneArg("CUSTEXTBITS",   &nParam, &szParam)) ubCustExt   = ParseBits(szParam);
  1719.     if (GetPhoneArg("CUSTMICBITS",   &nParam, &szParam)) ubCustMic   = ParseBits(szParam);
  1720.     if (GetPhoneArg("CUSTSAMPLEADDRESS", &nParam, &szParam)) pubCustSampleAt = ((UBYTE *) strtol(szParam, NULL, 16));
  1721.     if (GetPhoneArg("FONT", &nParam, &szParam)) 
  1722.     {
  1723.         strncpy(szFont,szParam,sizeof(szFont));
  1724.         LowerCase(szFont);
  1725.         UNLESS(strstr(szFont,".font")) strncat(szFont,".font",sizeof(szFont));
  1726.     }
  1727.     if (GetPhoneArg("FONTSIZE", &nParam, &szParam)) nFontSize = nParam;
  1728.  
  1729.     if (GetPhoneArg("DEBUG",     &nParam, &szParam)) BUserDebug = TRUE;
  1730.     if (GetPhoneArg("HACKAMPVOL",     &nParam, &szParam)) nHackAmpVol = nParam;
  1731.     /* Fill out "connect To" menu */
  1732.     for (i=0;i<10;i++)
  1733.     {
  1734.         sprintf(szTemp,"PHONEBOOK%i",i);
  1735.         SetPhoneEntry(((i==0) ? 9 : i-1), GetPhoneArg(szTemp, &nParam, &szParam) ? szParam : NULL);
  1736.     }
  1737.  
  1738.     /* Do this last, as it depends on previous constraints! */
  1739.     if (GetPhoneArg("XMITDELAY", &nParam, &szParam)) fPacketDelay = (((float)atoi(szParam))/1000.0);
  1740.     if (GetPhoneArg("PACKETINTERVAL", &nParam, &szParam)) fPacketDelay = (((float)atoi(szParam))/1000.0);
  1741.     
  1742.     /* Make sure the delay isn't too big or small */
  1743.     if (fPacketDelay < MIN_PACKET_INTERVAL)  fPacketDelay = MIN_PACKET_INTERVAL;
  1744.     if ((fPacketDelay * 1000.0) > nMaxDelay) fPacketDelay = (((float) nMaxDelay+1) / 1000.0);
  1745.     
  1746.         if (AmiPhoneIconDiskObject != NULL) 
  1747.         {
  1748.             FreeDiskObject(AmiPhoneIconDiskObject);
  1749.             AmiPhoneIconDiskObject = NULL;
  1750.             szPhoneFileName = NULL;
  1751.         }
  1752.         
  1753.         /* Last, if we just parsed the icon even though we're running from CLI, */
  1754.         /* now we want to parse the command line as well. */
  1755.         if (BFromCLIButParseIconToo) ParseArgs(FALSE);
  1756.  
  1757.     return;
  1758. }
  1759.  
  1760.  
  1761. /* nNum = 0 at first entry, 9 at last entry */
  1762. static void SetPhoneEntry(int nNum, char * szCode)
  1763. {
  1764.     char * szIP;
  1765.  
  1766.     if ((pszCallNames[nNum])||(pszCallIPs[nNum]))
  1767.     {
  1768.         /* no sense replacing something with nothing */
  1769.         if (szCode == NULL) return;
  1770.         
  1771.         /* Deallocate old data */
  1772.         if (pszCallNames[nNum]) {FreeMem(pszCallNames[nNum],strlen(pszCallNames[nNum])+1); pszCallNames[nNum] = NULL;}
  1773.         if (pszCallIPs[nNum])   {FreeMem(pszCallIPs[nNum],  strlen(pszCallIPs[nNum])  +1); pszCallIPs[nNum]   = NULL;}
  1774.     }
  1775.     
  1776.     
  1777.     UNLESS(szCode) szCode = "<unused>";
  1778.  
  1779.     if (szIP = strchr(szCode,':')) 
  1780.     {
  1781.         *szIP = '\0'; /* chop the string */
  1782.         if (pszCallIPs[nNum] = AllocMem(strlen(szIP+1)+1,MEMF_CLEAR)) strcpy(pszCallIPs[nNum],szIP+1);
  1783.     }
  1784.     if (pszCallNames[nNum] = AllocMem(strlen(szCode)+1,MEMF_CLEAR)) strcpy(pszCallNames[nNum],szCode);
  1785.  
  1786.     if (szIP) *szIP = ':';    /* repair the string */
  1787.     nmMenus[nNum+FIRST_CONNECT_TO].nm_Label = pszCallNames[nNum];
  1788. }
  1789.  
  1790.  
  1791.  
  1792. /* returns the value of szString as an unsigned byte.
  1793.    
  1794.    szString should look like "+S+P+B"
  1795.   
  1796.    Where any bits after a + are set, any after a - are cleared.  
  1797. */
  1798. static UBYTE ParseBits(char * szString)
  1799. {
  1800.     UBYTE ubResult = 0;
  1801.     char cSign = '+';
  1802.     char * pcTemp = szString;
  1803.     
  1804.     while(*pcTemp)
  1805.     {
  1806.         switch(*pcTemp)
  1807.         {
  1808.             case '+': case '-':  cSign = *pcTemp; break;
  1809.             
  1810.             case 'b': case 'B':
  1811.                 if (cSign == '+') ubResult |= SAMPBIT_BUSYSET;
  1812.                          else ubResult |= SAMPBIT_BUSYCLR;
  1813.                 break;
  1814.                 
  1815.  
  1816.             case 'p': case 'P':
  1817.                 if (cSign == '+') ubResult |= SAMPBIT_POUTSET;
  1818.                          else ubResult |= SAMPBIT_POUTCLR;
  1819.                 break;
  1820.  
  1821.             case 's': case 'S':
  1822.                 if (cSign == '+') ubResult |= SAMPBIT_SELSET;
  1823.                          else ubResult |= SAMPBIT_SELCLR;
  1824.                 break;                
  1825.         }
  1826.         pcTemp++;
  1827.     }
  1828.     return(ubResult);
  1829. }
  1830.  
  1831.  
  1832. BOOL IsKeyword(char * szWord)
  1833. {
  1834.     BOOL BReturn = FALSE;
  1835.     char szBuf[30];
  1836.     char *pcTemp;
  1837.     
  1838.     Strncpy(szBuf, szWord, sizeof(szBuf));
  1839.     UpperCase(szBuf);
  1840.     
  1841.     if (pcTemp = strchr(szBuf,'=')) *pcTemp='\0';
  1842.  
  1843.     BReturn = ((0==strcmp(szBuf,"TOP"))          ||
  1844.           (0==strcmp(szBuf,"LEFT"))         ||
  1845.           (0==strcmp(szBuf,"KEY"))          ||
  1846.            (0==strcmp(szBuf,"PUBSCREEN"))     ||
  1847.            (0==strcmp(szBuf,"THRESHVOLUME"))     ||
  1848.                (0==strcmp(szBuf,"MINVOLUME"))     ||
  1849.            (0==strcmp(szBuf,"XMITDELAY"))     ||
  1850.            (0==strcmp(szBuf,"PACKETINTERVAL"))     ||
  1851.            (0==strcmp(szBuf,"SAMPLERATE"))     ||
  1852.            (0==strcmp(szBuf,"ENABLEONCONNECT"))     ||
  1853.            (0==strcmp(szBuf,"XMITONCONNECT"))     ||
  1854.              (0==strcmp(szBuf,"XMITONPLAY"))     ||
  1855.              (0==strcmp(szBuf,"TCPBATCHXMIT"))     ||
  1856.            (0==strcmp(szBuf,"SENDPRI"))         ||
  1857.            (0==strcmp(szBuf,"RECEIVEPRI"))     ||
  1858.            (0==strcmp(szBuf,"HOLDTOTRANSMIT"))     ||
  1859.            (0==strcmp(szBuf,"COMPRESS"))     ||
  1860.            (0==strcmp(szBuf,"MAXBANDWIDTH"))     ||
  1861.            (0==strcmp(szBuf,"CONNECT"))         ||
  1862.            (0==strcmp(szBuf,"SAMPLETECHNIQUE"))     ||
  1863.            (0==strcmp(szBuf,"MAXSAMPLERATE"))     ||
  1864.            (0==strcmp(szBuf,"INPUTCHANNEL"))     ||
  1865.            (0==strcmp(szBuf,"SAMPLER"))         ||
  1866.            (0==strcmp(szBuf,"VOICEMAILDIR"))     ||
  1867.            (0==strcmp(szBuf,"INPUTSOURCE"))      ||
  1868.            (0==strcmp(szBuf,"AMPLIFY"))          ||
  1869.            (0==strcmp(szBuf,"PUBSCREEN"))    ||
  1870.            (0==strcmp(szBuf,"PUBLICSCREEN"))     ||
  1871.            (0==strcmp(szBuf,"CUSTSTARTBITS"))    ||
  1872.           (0==strcmp(szBuf,"CUSTDIRBITS"))     ||
  1873.           (0==strcmp(szBuf,"CUSTLEFTBITS"))    ||
  1874.           (0==strcmp(szBuf,"CUSTRIGHTBITS"))    ||
  1875.           (0==strcmp(szBuf,"CUSTEXTBITS"))    ||
  1876.           (0==strcmp(szBuf,"CUSTSTOPBITS"))    ||
  1877.           (0==strcmp(szBuf,"MAXXMITDELAY"))    ||
  1878.           (0==strcmp(szBuf,"MICGAIN"))        ||
  1879.           (0==strcmp(szBuf,"LINEGAIN"))        ||
  1880.           (0==strcmp(szBuf,"IDLERATE"))        ||
  1881.           (0==strncmp(szBuf,"PHONEBOOK",9))    ||
  1882.           (0==strcmp(szBuf,"CUSTSAMPLEADDRESS"))||
  1883.           (0==strcmp(szBuf,"MAXVOLBYTECOUNT"))  ||
  1884.           (0==strcmp(szBuf,"HACKAMPVOL"))      ||
  1885.           (0==strcmp(szBuf,"DEBUG"))          ||
  1886.           (0==strcmp(szBuf,"FONT"))          ||
  1887.           (0==strcmp(szBuf,"FONTSIZE"))      ||
  1888.           (0==strcmp(szBuf,"PRESEND"))      ||
  1889.           (0==strcmp(szBuf,"POSTSEND"))      ||
  1890.           (0==strcmp(szBuf,"CUSTMICBITS")));
  1891.  
  1892.     return(BReturn);
  1893. }
  1894.  
  1895. BOOL GetPhoneArg(char * szArg, int * nParam, char **szParam)
  1896. {
  1897.     /* szPhoneFileName is set if we want to force-load another icon file */
  1898.     if ((BStartedFromWB == TRUE)||(szPhoneFileName != NULL))
  1899.         return(GetToolTypeArg(szArg,nParam,szParam));
  1900.     else
  1901.         return(GetCLIArg(szArg,nParam,szParam));
  1902. }
  1903.  
  1904. /* Searches command line arguments for an argument of the form
  1905.    ARG, ARG=PARAM, or arguments of the form ARG PARAM
  1906.    
  1907.    That is, if ARG is found, the next argument will be returned
  1908.    as PARAM */
  1909. BOOL GetCLIArg(char *szArg, int *nParam, char **szParam)
  1910. {
  1911.     int i;
  1912.     char *pcTemp;
  1913.     char szTemp[50];
  1914.         
  1915.     /* argc, argv must be defined globally! */
  1916.     for (i=1;i<argc;i++)
  1917.     {
  1918.         Strncpy(szTemp,argv[i],sizeof(szTemp));
  1919.         UpperCase(szTemp);
  1920.         
  1921.         pcTemp = strchr(szTemp,'=');
  1922.         if (pcTemp != NULL) *pcTemp = '\0';
  1923.         
  1924.         if (strcmp(szTemp,szArg) == 0)
  1925.         {
  1926.             /* Found our argument! */
  1927.             
  1928.             /* Form is ARG=PARAM */
  1929.             if (pcTemp != NULL)
  1930.             {
  1931.                 *szParam = strchr(argv[i], '=') + 1;
  1932.                 *nParam  = atoi(pcTemp+1);
  1933.             }
  1934.             else
  1935.             {
  1936.                 if (argv[i+1] == NULL)
  1937.                 {
  1938.                     *szParam = "";
  1939.                     *nParam = 0;
  1940.                 }
  1941.                 else
  1942.                 {
  1943.                     *szParam = argv[i+1];
  1944.                     *nParam = atoi(argv[i+1]);
  1945.                 }
  1946.             }
  1947.             return(TRUE);
  1948.         }
  1949.     }
  1950.     return(FALSE);
  1951. }
  1952.  
  1953.  
  1954. BOOL SetupToolTypeArg(char * szExecName)
  1955. {
  1956.     struct WBArg *wb_arg = ((struct WBStartup *) argv)->sm_ArgList;
  1957.  
  1958.     /* szExecName is an override for the icon file name */
  1959.     if (szExecName)    AmiPhoneIconDiskObject = GetDiskObject((UBYTE *)szExecName);
  1960.            else AmiPhoneIconDiskObject = GetDiskObject((UBYTE *)wb_arg->wa_Name);
  1961.                 
  1962.     return(AmiPhoneIconDiskObject != NULL);
  1963. }
  1964.  
  1965.  
  1966.  
  1967. /* You must call SetupToolTypeArg before calling this function! */
  1968. BOOL GetToolTypeArg(char *szArg, int *nParam, char **szParam)
  1969. {
  1970.     static char sToolParam[200];
  1971.     char **toolarray = (char **) AmiPhoneIconDiskObject->do_ToolTypes;
  1972.     char *sTemp;
  1973.  
  1974.     /* Clear default string */
  1975.     sToolParam[0] = '\0';
  1976.     *szParam = sToolParam;    /* Return pointer to it */
  1977.             
  1978.     if ((toolarray != NULL) &&
  1979.         ((sTemp = (char *) FindToolType(toolarray,szArg)) != NULL))
  1980.     {
  1981.         *nParam = atoi(sTemp);
  1982.         Strncpy(sToolParam,sTemp,sizeof(sToolParam));
  1983.         return(TRUE);
  1984.     }                     
  1985.      return(FALSE);
  1986. }
  1987.  
  1988.  
  1989. void ConnectionEstablished(UBYTE ubType,int nPort, ULONG ulKBytesToRecord)
  1990. {
  1991.     char * szMessage;
  1992.     char szText[200];    
  1993.     int ulMaxSeconds;
  1994.     
  1995.     BNetConnect = TRUE;
  1996.     
  1997.     switch(ubType)
  1998.     {
  1999.         case PCREPLY_WILLLISTEN:     szMessage = "Peer is listening";           break;
  2000.         case PCREPLY_TWOWAY:         szMessage = "Connection established";      break;
  2001.         case PCREPLY_LEAVEMESSAGE:    szMessage = "Voice Mail";         break;
  2002.         case PCREPLY_CANTLEAVEMESSAGE:  szMessage = "No Voice Mail";        break;
  2003.         default:             szMessage = "Error, bad connect code";     break;
  2004.     }
  2005.     SetWindowTitle(szMessage);
  2006.  
  2007.     if (ubType == PCREPLY_CANTLEAVEMESSAGE)
  2008.     {
  2009.         MakeReq(NULL,"Your party is not available, and their voice mail box is either full or disabled.",NULL);
  2010.         ConnectionClosed(szMessage);
  2011.         return;
  2012.     }
  2013.     
  2014.     ChangeConnectPort(nPort);
  2015.  
  2016.     if (ubType == PCREPLY_LEAVEMESSAGE)
  2017.     {
  2018.         ulMaxSeconds = ulKBytesToRecord / (ulBytesPerSecond/1024);
  2019.         if (ubCurrComp == COMPRESS_ADPCM2) ulMaxSeconds *= 4;
  2020.         if (ubCurrComp == COMPRESS_ADPCM3) ulMaxSeconds *= (8/3);
  2021.         
  2022.         sprintf(szText,"Your party at %s is not available right now.\nWould you like to leave a message?\n(Max message length with current settings is %i seconds)",
  2023.             szPeerName, ulMaxSeconds);
  2024.         if (MakeReq(NULL,szText,"Leave Message|Cancel") == 1)
  2025.         {
  2026.             SetWindowTitle("Leave a message now.");
  2027.         }
  2028.         else
  2029.         {
  2030.             ClosePhoneSocket();
  2031.             SetMenuValues();
  2032.             SetWindowTitle("No message left.");
  2033.             return;
  2034.         }
  2035.     }
  2036.             
  2037.     SetMenuValues();
  2038.     if ((BEnableOnConnect == TRUE)&&(nToggleMode == TOGGLE_TOGGLE)) ToggleMicButton(CODE_ON);
  2039. }
  2040.  
  2041.  
  2042. void ConnectionClosed(char * szReason)
  2043. {
  2044.     BNetConnect = FALSE;    /* keep us from sending a disconnect packet when the connection is already closed */
  2045.     ClosePhoneSocket();
  2046.     SetWindowTitle(szReason);
  2047. }
  2048.  
  2049.  
  2050. void ProcessReply(void)
  2051. {    
  2052.     struct AmiPhoneSendBuffer * packet;
  2053.     
  2054.     if (SocketBase == NULL) return;
  2055.     errno = 0;    /* errno at a known state--hope there is no asynchronous bs going on here! */
  2056.     UNLESS(packet = GetTCPPacket(sTCPSocket)) 
  2057.     {
  2058.         if ((errno > 0)&&(errno != EWOULDBLOCK))
  2059.         {
  2060.             char szError[50];            
  2061.             sprintf(szError,"Receive Error %i", errno);
  2062.             ConnectionClosed(szError);
  2063.         }
  2064.         return;
  2065.     }    
  2066.     switch(packet->header.ubCommand)
  2067.     {
  2068.         case PHONECOMMAND_REPLY:    ConnectionEstablished(packet->header.ubType,packet->header.ulBPS,packet->header.ulJoinCode);  break;
  2069.         case PHONECOMMAND_DENY:      ConnectionClosed("Connection denied.");             break;
  2070.         case PHONECOMMAND_DISCONNECT:    ConnectionClosed("Connection closed.");             break;
  2071.         case PHONECOMMAND_VWARN:    CheckVersions("AmiPhoned server", packet->header.ulBPS, TRUE); break;
  2072.         default: printf("ProcessReply: bad command [%c %i]\n",packet->header.ubCommand, packet->header.ubCommand);
  2073.     }
  2074. }
  2075.  
  2076.  
  2077. void SetTimer(struct timerequest * tio, int nSecs, int nMicros)
  2078. {
  2079.      /* First make sure there is no previous timer pending */
  2080.         if (!(CheckIO((struct IORequest *) tio)))
  2081.         {
  2082.             AbortIO((struct IORequest *) tio);
  2083.             WaitIO((struct IORequest *) tio);
  2084.         }
  2085.                
  2086.         tio->tr_time.tv_secs  = nSecs;                                        
  2087.         tio->tr_time.tv_micro = nMicros;
  2088.         
  2089.         /* Start ze timer */
  2090.         SendIO((struct IORequest *)tio);
  2091. }
  2092.  
  2093.  
  2094. void SetupGraphicsInfo(struct AmiPhoneGraphicsInfo * inf)
  2095. {
  2096.     inf->GraphMessage.mn_Node.ln_Type     = NT_MESSAGE;
  2097.     inf->GraphMessage.mn_Length         = sizeof(struct AmiPhoneGraphicsInfo);
  2098.     inf->GraphMessage.mn_ReplyPort        = NULL;
  2099.     
  2100.     inf->ubCommand        = MSG_CONTROL_HI | MSG_CONTROL_DOANIM;
  2101.     inf->nImageTop        = IMAGE_NOCONN;
  2102.     inf->ubCurrLocalComp    = COMPRESS_NONE;
  2103.     inf->ubCurrRemoteComp    = COMPRESS_NONE;
  2104.     inf->nBarHeightR    = 0;
  2105.     inf->nBarHeightS    = 0;
  2106.     inf->BErrorR        = FALSE;
  2107.     inf->BErrorS        = FALSE;
  2108. }
  2109.  
  2110. BOOL SafePutToPort(struct Message * message, char * portname)
  2111. {
  2112.         struct MsgPort * dport;
  2113.  
  2114.         Forbid();
  2115.         dport = FindPort(portname);
  2116.         if (dport) PutMsg(dport, message);
  2117.         Permit();
  2118.     
  2119.         return(dport ? TRUE : FALSE);
  2120. }
  2121.  
  2122. void CreateGraphicsDaemon(struct AmiPhoneGraphicsInfo * ginfo)
  2123. {    
  2124.     if (ginfo != NULL)
  2125.     {
  2126.         SetupGraphicsInfo(ginfo);
  2127.         UNLESS (GraphicDaemonProcess = CreateNewProcTags(
  2128.             NP_Entry,     GraphicsTaskMain, 
  2129.             NP_Name,      "AmiPhone Graphics Update",
  2130.             NP_Priority,    -6, 
  2131.             TAG_END)) 
  2132.           EXIT("Couldn't create graphics daemon",RETURN_ERROR)
  2133.     }
  2134. }    
  2135.  
  2136.  
  2137.  
  2138.  
  2139. /* This is where the Graphics Daemon starts executing at! */
  2140. __geta4 void GraphicsTaskMain(void)
  2141. {
  2142.     /* Global data to be used by the graphics daemon ONLY */
  2143.     struct GfxBase * GfxBase = NULL;
  2144.     struct Library * IntBase = NULL;
  2145.     ULONG ulDMask, signals;
  2146.     UBYTE ubCommands;
  2147.     int nDot=0;
  2148.     int i, nVolHeight, nHeight;
  2149.     struct RastPort myRast;
  2150.     
  2151.     /* Record that we are running */
  2152.     BGraphicsDaemon = TRUE;
  2153.     
  2154.     /* Make our own, local copy of the RastPort */
  2155.     memcpy(&myRast,PhoneWindow->RPort, sizeof(myRast));
  2156.         
  2157.     UNLESS ((GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",37)) &&
  2158.             (IntBase = (struct GfxBase *)OpenLibrary("intuition.library",37))) 
  2159.     {
  2160.         BGraphicsDaemon     = FALSE;
  2161.         GraphInfo.ubCommand = MSG_CONTROL_IMLEAVING; 
  2162.         return;
  2163.     }
  2164.  
  2165.     ulDMask = SIGBREAKF_CTRL_F | SIGBREAKF_CTRL_C;
  2166.  
  2167.     /* The event loop */
  2168.     while(1)
  2169.     {
  2170.         signals = Wait(ulDMask);
  2171.                 
  2172.         if (signals & SIGBREAKF_CTRL_C) break;
  2173.         if (signals & SIGBREAKF_CTRL_F)
  2174.         {    
  2175.             /* CRITICAL SECTION */
  2176.             Forbid();
  2177.             ubCommands = GraphInfo.ubCommand;
  2178.             GraphInfo.ubCommand = 0;
  2179.             Permit();
  2180.             /* END CRITICAL SECTION */
  2181.  
  2182.             if (ubCommands & MSG_CONTROL_HI)
  2183.             {
  2184.                 /* um, nothing to do really for now */
  2185.             }
  2186.  
  2187.             if ((ubCommands & MSG_CONTROL_DOTITLE)&&(PhoneWindow))
  2188.                 SetWindowTitles(PhoneWindow, szWinTitle, (char *) ~0);
  2189.         
  2190.             if (ubCommands & MSG_CONTROL_BYE) break;
  2191.         
  2192.             if ((BZoomed == FALSE)&&(ubCommands & MSG_CONTROL_DOGRAPH))
  2193.             {
  2194.                 if (BNetConnect)
  2195.                 {
  2196.                     /* Update graph */
  2197.                     ScrollRaster(&myRast, 1, 0, nRecGraphLeft, nRecGraphTop, nRecGraphRight, nRecGraphBottom);
  2198.                     
  2199.                     SetAPen(&myRast,(GraphInfo.BErrorR ? COLOR_RECEIVE_ERROR : COLOR_RECEIVE));
  2200.                     GraphInfo.BErrorR = FALSE;
  2201.                     Move(&myRast,nRecGraphRight,nRecGraphBottom);
  2202.                     nHeight = nRecGraphBottom-GraphInfo.nBarHeightR;
  2203.                     if ((nHeight < nRecGraphTop)||(nHeight > nRecGraphBottom)) nHeight = nRecGraphTop;
  2204.                     if (GraphInfo.nBarHeightR > 0) Draw(&myRast,nRecGraphRight,nHeight);
  2205.                     SetAPen(&myRast,(GraphInfo.BErrorS ? COLOR_SEND_ERROR : COLOR_SEND));
  2206.                     GraphInfo.BErrorS = FALSE;
  2207.                     nHeight = nRecGraphBottom-GraphInfo.nBarHeightS;
  2208.                     if ((nHeight < nRecGraphTop)||(nHeight > nRecGraphBottom)) nHeight = nRecGraphTop;
  2209.                     if (GraphInfo.nBarHeightS > 0) Draw(&myRast, nRecGraphRight, nHeight);
  2210.     
  2211.                     /* draw standards lines */
  2212.                     SetAPen(&myRast, 1);    
  2213.                     i=0;        
  2214.                     while (nDot==0)
  2215.                     {
  2216.                         i += HEIGHT144;
  2217.                         if (i > MAXHEIGHT) break;
  2218.                         WritePixel(&myRast,nRecGraphRight,nRecGraphBottom-i);
  2219.                     }
  2220.                     nDot = (nDot+1)%DOTSPACING;
  2221.                 }
  2222.             }
  2223.                                     
  2224.             if ((BZoomed == FALSE)&&(ubCommands & MSG_CONTROL_DOANIM))
  2225.             {
  2226.                 /* Draw the microphone image */
  2227.                 BltBitMapRastPort(&MicBitMap, 0, (GraphInfo.nImageTop)*MIC_HEIGHT,
  2228.                     &myRast, MIC_LEFT, nMicTop, MIC_WIDTH, MIC_HEIGHT, 0xC0);        
  2229.                 
  2230.                 /* Draw the volume indicator */
  2231.                 nVolHeight = ChopValue((CalcVolumePercentage(ulLastVolume)*MAXHEIGHT)/100, 0, MAXHEIGHT-1);
  2232.                 SetAPen(&myRast, 0);
  2233.                 RectFill(&myRast, VOLBARLEFT, VOLBARTOP, VOLBARRIGHT, nVolBarBottom-nVolHeight);
  2234.                 SetAPen(&myRast, 7);
  2235.                 if (nVolHeight > 0) RectFill(&myRast, VOLBARLEFT, nVolBarBottom-nVolHeight, VOLBARRIGHT, nVolBarBottom);
  2236.                 SetAPen(&myRast, 1);
  2237.                 Move(&myRast, VOLBARLEFT,  nVolBarBottom-(nMinSampleVol * MAXHEIGHT / 99));
  2238.                 Draw(&myRast, VOLBARRIGHT, nVolBarBottom-(nMinSampleVol * MAXHEIGHT / 99));
  2239.             }
  2240.         }
  2241.     }
  2242.     if (IntBase) CloseLibrary(IntBase);
  2243.     if (GfxBase) CloseLibrary((struct Library *)GfxBase);
  2244.     BGraphicsDaemon = FALSE;
  2245.     GraphInfo.ubCommand = MSG_CONTROL_IMLEAVING;
  2246.     return;
  2247. }
  2248.  
  2249.  
  2250. void DrawWindowBoxes(void)
  2251. {
  2252.     DrawHitBox(nRecGraphLeft-1, nRecGraphTop-1, nRecGraphRight+1, nRecGraphBottom+1, 0, TRUE);
  2253.     DrawHitBox(VOLBARLEFT-1, VOLBARTOP-1, VOLBARRIGHT+1, nVolBarBottom+1, 0, TRUE);
  2254. }
  2255.  
  2256.  
  2257. /* Handles requests to output sound via the asynchronous sound player! */
  2258. static void HandleSoundPort(BOOL BAllowNewPlayers)
  2259. {
  2260.     struct PlayerMessage * PMessage;
  2261.     
  2262.     /* Reply the message */
  2263.     while(PMessage = (struct PlayerMessage *)GetMsg(SoundTaskPort))
  2264.     {
  2265.         switch(PMessage->ubControl)
  2266.         {
  2267.             case MESSAGE_CONTROLMAIN_REQCLOSED:
  2268.                 FileReqTask = NULL;
  2269.                 break;
  2270.  
  2271.             case MESSAGE_CONTROLMAIN_STOPPLAYING:
  2272.                 if (BAllowNewPlayers) StopSoundPlayer(FALSE);
  2273.                 break;
  2274.  
  2275.             case MESSAGE_CONTROLMAIN_PLAYFILE:
  2276.                 /* Should only be called from the FileReq and Message Browser processes! */
  2277.                 if (BAllowNewPlayers) StartSoundPlayer((char *) PMessage->data);
  2278.                 break;
  2279.  
  2280.             case MESSAGE_CONTROLMAIN_IMLEAVING:
  2281.                 SoundPlayerTask = NULL;
  2282.                 if (BWasSamplingBefore == TRUE) 
  2283.                 {
  2284.                     BWasSamplingBefore = FALSE;
  2285.                     ToggleMicButton(CODE_ON);
  2286.                 }
  2287.                 else DrawMicButton(-1);
  2288.                 if (BXmitOnPlay) SendCommandPacket(PHONECOMMAND_FLUSH,0,0L);
  2289.                 break;
  2290.                     
  2291.             case MESSAGE_CONTROLMAIN_XMITPACKET:
  2292.                 if ((BNetConnect)&&(BXmitOnPlay)&&(BAllowNewPlayers))
  2293.                     SendPacket((struct AmiPhoneSendBuffer *)PMessage->data, BTCPBatchXmit);
  2294.                 break;
  2295.                 
  2296.             case MESSAGE_CONTROLMAIN_BROWSEROPEN:
  2297.                 BBrowserIsRunning = TRUE;
  2298.                 break;
  2299.                 
  2300.             case MESSAGE_CONTROLMAIN_BROWSERCLOSED:
  2301.                 BBrowserIsRunning = FALSE;
  2302.                 break;
  2303.  
  2304.             default:
  2305.                 printf("HandleSoundPort:  Bad PlayerMessage type [%i]\n",PMessage->ubControl);
  2306.                 break;
  2307.         }
  2308.         ReplyMsg((struct Message *)PMessage);
  2309.     }
  2310. }
  2311.         
  2312.  
  2313. /* Intelligently adds/removes PhonePort */
  2314. void AddPhonePort(BOOL BAdd)
  2315. {
  2316.     static BOOL BAdded = FALSE;
  2317.     
  2318.     if (BAdd == BAdded) return;
  2319.     
  2320.     if (BAdd == TRUE) AddPort(PhonePort);
  2321.              else RemPort(PhonePort);
  2322.  
  2323.     BAdded = BAdd;
  2324.     return;
  2325. }
  2326.  
  2327. int MakeReq(char *sTitle, char *sText, char *sGadgets)
  2328. {
  2329.     struct EasyStruct myreq;
  2330.     LONG number = 0L;
  2331.     int nResult;
  2332.  
  2333.     UNLESS(sTitle)   sTitle   = "AmiPhone Message";
  2334.     UNLESS(sText)    sText    = "Hey, something's up!";
  2335.     UNLESS(sGadgets) sGadgets = "OK";
  2336.  
  2337.     myreq.es_TextFormat   = sText;
  2338.     myreq.es_Title        = sTitle;
  2339.     myreq.es_GadgetFormat = sGadgets;
  2340.  
  2341.     nResult = EasyRequest(NULL, &myreq, NULL, NULL, number);
  2342.  
  2343.     return(nResult);
  2344. }
  2345.  
  2346.  
  2347.  
  2348.  
  2349.  
  2350. static BOOL AllocAHI(BOOL BAlloc)
  2351. {
  2352.   ULONG id=0;
  2353.   
  2354.   if (BAlloc)
  2355.   {  
  2356.       UNLESS
  2357.        ((AHImp = CreateMsgPort()) && 
  2358.         (AHIio = (struct AHIRequest *)CreateIORequest(AHImp,sizeof(struct AHIRequest))) &&
  2359.         (AHIio->ahir_Version = 1) &&
  2360.         ((AHIDevice = OpenDevice(AHINAME,AHI_NO_UNIT,(struct IORequest *)AHIio,0L)) == 0))
  2361.       {
  2362.           /* Oops, something went awry--clean up and fail! */
  2363.           AllocAHI(FALSE);
  2364.           return(FALSE);
  2365.       }
  2366.     AHIBase=(struct Library *)AHIio->ahir_Std.io_Device;
  2367.   }
  2368.   else
  2369.   {    
  2370.       if (!AHIDevice) CloseDevice((struct IORequest *)AHIio); AHIDevice = -1;
  2371.       if (AHIio) DeleteIORequest((struct IORequest *) AHIio); AHIio = NULL;
  2372.       if (AHImp) DeleteMsgPort(AHImp); AHImp = NULL;
  2373.       AHIBase = NULL;
  2374.   }
  2375.   return(TRUE);
  2376. }
  2377.  
  2378.  
  2379.  
  2380.  
  2381. static void HandleAppWindow(void)
  2382. {    
  2383.     BOOL BSoundPlayed = FALSE;
  2384.     struct AppMessage * amsg;
  2385.     struct WBArg *argptr = NULL;
  2386.     char szFilePath[500];
  2387.     
  2388.     UNLESS(AppWindowPort) return;
  2389.     
  2390.     while (amsg = (struct AppMessage *) GetMsg(AppWindowPort))
  2391.     {
  2392.         /* Only start one sound at a time.  Ignore the other messages */
  2393.         UNLESS(BSoundPlayed)
  2394.         {    
  2395.             /* process messages--only 1st file, no point in dropping more than one at a time! */
  2396.             if (amsg->am_NumArgs > 0L)
  2397.             {
  2398.                 if (NameFromLock(amsg->am_ArgList[0].wa_Lock, szFilePath, sizeof(szFilePath)))
  2399.                 {
  2400.                     AddPart(szFilePath, amsg->am_ArgList[0].wa_Name, sizeof(szFilePath));    
  2401.                     StopSoundPlayer(FALSE);
  2402.                     StartSoundPlayer(szFilePath);
  2403.                     BSoundPlayed = TRUE;
  2404.                 }
  2405.             }
  2406.         }
  2407.         /* done with message, release it */
  2408.         ReplyMsg((struct Message *)amsg);
  2409.     }
  2410. }
  2411.  
  2412.  
  2413. /* Returns info about the Slider's dimensions in the current screen's font */
  2414. static void GetSliderInfo(int * pnLabelWidth, int * pnValueWidth, int * pnHeight)
  2415. {
  2416.     int nMaxLabelWidth = 0, nMaxValueWidth = 0, nTemp;
  2417.     struct RastPort * rp = &Scr->RastPort;
  2418.     struct RastPort dummyrastport;
  2419.     struct TextExtent te;
  2420.  
  2421.     if (fontdata)
  2422.     {
  2423.         InitRastPort(&dummyrastport);
  2424.         SetFont(&dummyrastport, fontdata);    
  2425.         rp = &dummyrastport;
  2426.     }
  2427.     
  2428.     /* Get font height */
  2429.     if (pnHeight)
  2430.     {    
  2431.         TextExtent(rp, szSliderLabel1, sizeof(szSliderLabel1), &te);
  2432.         *pnHeight = te.te_Height;
  2433.     }
  2434.  
  2435.     /* Get width of widest slider label */
  2436.     if (pnLabelWidth)
  2437.     {
  2438.         if ((nTemp = TextLength(rp, szSliderLabel1, sizeof(szSliderLabel1))) > nMaxLabelWidth) nMaxLabelWidth = nTemp;
  2439.         if ((nTemp = TextLength(rp, szSliderLabel2, sizeof(szSliderLabel2))) > nMaxLabelWidth) nMaxLabelWidth = nTemp;
  2440.         if ((nTemp = TextLength(rp, szSliderLabel3, sizeof(szSliderLabel3))) > nMaxLabelWidth) nMaxLabelWidth = nTemp;
  2441.         UNLESS(BPropFont) nMaxLabelWidth = nMaxLabelWidth * 10 / 9;
  2442.         *pnLabelWidth = nMaxLabelWidth;
  2443.     }
  2444.     /* Get width of widest possible slider value */
  2445.     if (pnValueWidth)
  2446.     {
  2447.         if ((nTemp = TextLength(rp, szSliderValue1, sizeof(szSliderValue1))) > nMaxValueWidth) nMaxValueWidth = nTemp;
  2448.         if ((nTemp = TextLength(rp, szSliderValue2, sizeof(szSliderValue2))) > nMaxValueWidth) nMaxValueWidth = nTemp;
  2449.         if ((nTemp = TextLength(rp, szSliderValue3, sizeof(szSliderValue3))) > nMaxValueWidth) nMaxValueWidth = nTemp;
  2450.         UNLESS(BPropFont) nMaxValueWidth = nMaxValueWidth * 10 / 9;
  2451.         *pnValueWidth = nMaxValueWidth;
  2452.     }
  2453. }
  2454.  
  2455.  
  2456. static int CalcWindowHeight(int nFontHeight)
  2457. {
  2458.     int nHeight = ((Scr->Font->ta_YSize + VSPACE) + (nFontHeight+VSPACE)*3 + VSPACE);
  2459.     return ((nHeight < WINDOWHEIGHT) ? WINDOWHEIGHT : nHeight);
  2460. }
  2461.  
  2462. static int CalcWindowWidth(int nLabelWidth, int nValueWidth)
  2463. {
  2464.     return ((MIC_LEFT+MIC_WIDTH+HSPACE+(VOLBARRIGHT-VOLBARLEFT)+HSPACE+SLIDER_WIDTH+nLabelWidth+nValueWidth)*6/5);
  2465. }
  2466.  
  2467.  
  2468. /* main program code */
  2469. int main(int largc, char *largv[])
  2470. {
  2471.     char * szErrorLib;
  2472.     char szErrorMessage[100];
  2473.     int nSamp=0, nTemp1, nTemp2, nTemp3, nWidth, nHeight;
  2474.     ULONG signal;
  2475.     ULONG PhoneWinSigMask;
  2476.     struct Message * DMessage;
  2477.     UWORD wZoomCoords[4];
  2478.  
  2479.     /* Put this to a known state of non-allocation! */
  2480.     DelfinaBase = NULL;
  2481.         
  2482.     if ((BStartedFromWB == FALSE)&&(largc == 2)&&(*largv[1] == '?'))
  2483.     {
  2484.         printf("Template:  AmiPhone PEERNAME/A,TOP/K/N,LEFT/K/N,PUBSCREEN/K,COMPRESS/K,CONNECT/K,THRESHVOLUME/K/N,SAMPLERATE/K/N,XMITDELAY/K/N,MAXBANDWIDTH/K/N,SAMPLETECHNIQUE/K,MAXXMITDELAY/K/N,MAXSAMPLERATE/K/N,SAMPLER/K,VOICEMAILDIR/K,AMPLIFY/K/N,INPUTSOURCE/K,PHONEBOOKx/K,MICGAIN/K/N,IDLERATE/K/N,ENABLEONCONNECT/S,XMITONPLAY/S,HOLDTOTRANSMIT/S,TCPBATCHXMIT/S,INVERTWAVEFORM/S\n");
  2485.         exit(0);
  2486.     }    
  2487.     
  2488.     atexit(CleanExit);
  2489.     
  2490.     /* make startup args global! */
  2491.     argc = largc;
  2492.     argv = largv;
  2493.     
  2494.     /* initialize the dummy message */
  2495.     defMsg.ubControl        = MSG_CONTROL_INVALID;    
  2496.     defMsg.ulLastPacketSize        = 0L;    
  2497.     defMsg.daemonTask        = NULL;
  2498.     defMsg.BWindowIsOpen        = FALSE;
  2499.         
  2500.     if (szErrorLib = OpenLibraries(TRUE))
  2501.     {
  2502.         if (strcmp(szErrorLib,"bsdsocket"))
  2503.             sprintf(szErrorMessage,"Couldn't open %s.library", szErrorLib);
  2504.            else sprintf(szErrorMessage,"AmiTCP isn't running!");
  2505.         EXIT(szErrorMessage,RETURN_ERROR);
  2506.     }
  2507.     
  2508.     UNLESS(MiscBase = (struct Library *)OpenResource(MISCNAME)) EXIT("Couldn't open misc.resource",RETURN_ERROR)
  2509.     UNLESS(SetupPreSendQueue(TRUE))    EXIT("Couldn't setup presend queue", RETURN_ERROR)
  2510.     UNLESS(SetupTCPQueue(0,TRUE)) EXIT("Couldn't setup TCP queue", RETURN_ERROR)
  2511.     
  2512.     /* This reads in all args from command line or tooltypes, and sets global vars */
  2513.     ParseArgs(Not[BStartedFromWB]);
  2514.     
  2515.     /* Now that we've got all of the args, we can calc & set sample speed */
  2516.     ChangeSampleSpeed(ulBytesPerSecond,ubCurrComp);
  2517.     
  2518.     /* Set up our message ports */
  2519.     UNLESS (PhonePort = CreateMsgPort()) EXIT("Couldn't create graphics message port",RETURN_ERROR)
  2520.     UNLESS (SoundTaskPort = CreateMsgPort()) EXIT("Couldn't create soundtask message port",RETURN_ERROR)
  2521.  
  2522.     /* Set up the timer device ports */
  2523.     UNLESS (GraphicTimerMP = CreatePort(0,0)) EXIT("Couldn't create graphics timer message port",RETURN_ERROR)
  2524.     UNLESS (GraphicTimerIO = (struct timerequest *) CreateExtIO(GraphicTimerMP, (sizeof (struct timerequest))))
  2525.             EXIT("Couldn't create graphics timer IO request",RETURN_ERROR);
  2526.  
  2527.     /* Allow access to timer device's library functions */
  2528.     TimerBase = (struct Library *) GraphicTimerIO->tr_node.io_Device;
  2529.  
  2530.     /* Open the timer.device with UNIT_WAITUNTIL for graphics updates */
  2531.     if (OpenDevice(TIMERNAME,UNIT_VBLANK,(struct IORequest *)GraphicTimerIO,0))
  2532.             EXIT("Couldn't open timer.device",RETURN_ERROR);
  2533.  
  2534.     GraphicTimerIO->tr_node.io_Message.mn_ReplyPort = GraphicTimerMP;
  2535.     GraphicTimerIO->tr_node.io_Command = TR_ADDREQUEST;
  2536.     GraphicTimerIO->tr_node.io_Flags = 0;
  2537.     GraphicTimerIO->tr_node.io_Error = 0;
  2538.     GraphicTimerIO->tr_time.tv_secs  = 0;
  2539.     GraphicTimerIO->tr_time.tv_micro = 0; 
  2540.  
  2541.     UNLESS(AllocSignals(TRUE)) EXIT("Couldn't allocate signals!",RETURN_ERROR)
  2542.     UNLESS(Scr = LockPubScreen((strlen(szPubScreenName)>0) ? szPubScreenName : NULL)) 
  2543.     {
  2544.         printf("Couldn't open public screen, falling back to default public screen.\n");
  2545.         UNLESS (Scr = LockPubScreen(NULL)) EXIT("Couldn't lock the default public screen!",RETURN_ERROR);
  2546.     }
  2547.     
  2548.     /* Default = center window */
  2549.     if (windowtop  == -1) windowtop  = (Scr->Height>>1)-(WINDOWHEIGHT>>1);
  2550.     if (windowleft == -1) windowleft = (Scr->Width>>1)-(WINDOWWIDTH>>1);
  2551.  
  2552.     UNLESS(AllocSliders(TRUE)) EXIT("No slider gadgets",RETURN_ERROR)
  2553.  
  2554.     /* Open xmit window */
  2555.     sprintf(szErrorMessage,"AmiPhone v%i.%i", VERSION_NUMBER/100,VERSION_NUMBER%100);
  2556.     
  2557.     GetSliderInfo(&nTemp1, &nTemp2, &nTemp3);
  2558.     nHeight = CalcWindowHeight(nTemp3);
  2559.     nWidth  = CalcWindowWidth(nTemp1, nTemp2);
  2560.         
  2561.     if ((nWidth > Scr->Width)||(nHeight >Scr->Height)) EXIT("Couldn't create GUI, font too big for screen",RETURN_FAIL);
  2562.  
  2563.     /* specify what we look like when zoomed */
  2564.     wZoomCoords[0] = windowleft;
  2565.     wZoomCoords[1] = windowtop;
  2566.     wZoomCoords[2] = nWidth;
  2567.     wZoomCoords[3] = Scr->Font->ta_YSize+3;
  2568.     
  2569.         UNLESS(PhoneWindow = OpenWindowTags( NULL,
  2570.         WA_Left,        windowleft,
  2571.             WA_Top,         windowtop,
  2572.             WA_Width,       nWidth,
  2573.             WA_Height,      nHeight,
  2574.             WA_PubScreen,   Scr,
  2575.             WA_PubScreenFallBack, TRUE,
  2576.             WA_IDCMP,       IDCMP_MENUPICK|IDCMP_REFRESHWINDOW|IDCMP_CLOSEWINDOW|
  2577.                               IDCMP_MOUSEBUTTONS|SLIDERIDCMP|IDCMP_VANILLAKEY|IDCMP_NEWSIZE,
  2578.             WA_Flags,       WFLG_SIZEBBOTTOM|WFLG_SMART_REFRESH|WFLG_ACTIVATE|
  2579.                              /*WFLG_NEWLOOKMENUS|*/WFLG_CLOSEGADGET|WFLG_DRAGBAR|
  2580.                             WFLG_DEPTHGADGET,
  2581.             WA_Gadgets,    glist,
  2582.         WA_Zoom,    wZoomCoords,
  2583.         WA_Title,       szErrorMessage,
  2584.                WA_ScreenTitle, szProgramName,
  2585.                WA_DepthGadget, TRUE,
  2586.                WA_CloseGadget, TRUE,
  2587.                WA_SizeGadget,  FALSE,
  2588.                WA_DragBar,    TRUE,
  2589.                WA_AutoAdjust,  TRUE,
  2590.                WA_Activate,    TRUE,
  2591.         TAG_DONE ))
  2592.         EXIT("Couldn't open AmiPhone window!",RETURN_ERROR)
  2593.  
  2594.     /* Partition out the rest of the space for the graph */
  2595.     nRecGraphTop    = WID_TOP+1;
  2596.     nVolBarBottom   = nRecGraphBottom = PhoneWindow->Height - Scr->WBorBottom-(VSPACE*2);
  2597.     nMicTop        = nRecGraphTop + ((nRecGraphBottom-nRecGraphTop)/2) - (MIC_HEIGHT/2);
  2598.     nRecGraphRight  = PhoneWindow->Width - Scr->WBorRight-(HSPACE*2);
  2599.     nRecGraphLeft   = nTemp1+nTemp2+SLIDER_WIDTH+MIC_LEFT+MIC_WIDTH+(VOLBARRIGHT-VOLBARLEFT)+(HSPACE*4);
  2600.  
  2601.     GT_RefreshWindow(PhoneWindow, NULL);
  2602.     UNLESS(CreatePhoneMenus(TRUE)) EXIT("Couldn't Create Menus!",RETURN_ERROR)
  2603.  
  2604.     InitMicButton();    
  2605.     SetMenuValues();
  2606.  
  2607.     /* Draw receive graph outline */
  2608.     DrawWindowBoxes();    
  2609.  
  2610.     /* Setup the AppWindow stuff */
  2611.     if ((WorkbenchBase)&&(AppWindowPort = CreateMsgPort()))
  2612.     {
  2613.         UNLESS(AppWindow = AddAppWindowA(1, 0, PhoneWindow, AppWindowPort, NULL))
  2614.         {
  2615.             DeleteMsgPort(AppWindowPort);
  2616.             AppWindowPort = NULL;
  2617.         }
  2618.     }
  2619.  
  2620.     /* Setup the ARexx stuff */
  2621.     if (RexxSysBase) rexxHost = SetupARexxHost("AMIPHONE", NULL);
  2622.  
  2623.     PhoneWinSigMask = ((1L << PhoneWindow->UserPort->mp_SigBit) |
  2624.                (1L<<sighalf)                            | 
  2625.                (1L<<sigfull)                            | 
  2626.                (SIGBREAKF_CTRL_C)                       |
  2627.                (SIGBREAKF_CTRL_D)                       |
  2628.                (SIGBREAKF_CTRL_F)                       |
  2629.                (1L << GraphicTimerMP->mp_SigBit)        |  
  2630.                (1L << PhonePort->mp_SigBit)             | 
  2631.                (1L << SoundTaskPort->mp_SigBit)        |
  2632.                   (AppWindowPort ? (1L<<AppWindowPort->mp_SigBit) : 0)  |
  2633.                (rexxHost ? (1L<<rexxHost->port->mp_SigBit) : 0)      |
  2634.                (DelfinaBase ? delfsig : 0));
  2635.  
  2636.     /* Fill out our message to the graphics daemon */
  2637.     CreateGraphicsDaemon(&GraphInfo);
  2638.  
  2639.     /* Get our address */
  2640.     MainTask = FindTask(NULL);
  2641.     
  2642.     /* Set our priority to the proper value */
  2643.     if (nSendPri < 128) nOldSendPri = SetTaskPri(MainTask, nSendPri);
  2644.     
  2645.     /* Start the graphics update timer going */
  2646.     GTIMERGO;    
  2647.  
  2648.     /* This will set the Window title if someone is using our stuff */
  2649.     AllocParallel(CHECK_STATUS,FALSE);
  2650.  
  2651.     /* Put an initial draw in, just so we don't get that 1/2 second lag... it looks dumb */
  2652.     ulLastVolume = SILENCE;
  2653.     DrawMicButton(-1);
  2654.  
  2655.     SetExitMessage("CTRL-C detected",RETURN_ERROR);
  2656.  
  2657.     if ((strlen(szPeerName) > 0)&&(SocketBase))
  2658.     {
  2659.         ConnectPhoneSocket(FALSE,szPeerName);
  2660.         DrawMicButton(-1);
  2661.     }
  2662.  
  2663.     /* Main loop */
  2664.     while (BProgramDone == FALSE) 
  2665.     {    
  2666.         signal = PhoneWait(PhoneWinSigMask);
  2667.  
  2668.         if (signal & (1<<sighalf)) TransmitData(pubAllocedArray, ALL_OF_BUFFER, ubCurrComp);  /* send left buffer */
  2669.         if (signal & (1<<sigfull)) TransmitData(pubRightBuffer,  ALL_OF_BUFFER, ubCurrComp);  /* send right buffer */ 
  2670.  
  2671.         if ((DelfinaBase)&&(signal & delfsig))
  2672.         {
  2673.             int nBytesAfterComp = ulSampleArraySize;
  2674.             
  2675.             if (ubCurrComp == COMPRESS_ADPCM2) nBytesAfterComp >>= 2;
  2676.             if (ubCurrComp == COMPRESS_ADPCM3) nBytesAfterComp = (nBytesAfterComp * 3)>>3;
  2677.  
  2678.             TransmitData(pubAllocedArray, nBytesAfterComp, ubCurrComp);
  2679.         }
  2680.                 
  2681.         if ((signal & SIGBREAKF_CTRL_F)&&((ubSamplerType == SAMPLER_TOCCATA)||(ubSamplerType == SAMPLER_AHI)))
  2682.         {
  2683.             UBYTE * pubData;
  2684.             ULONG ulDataLen;
  2685.             
  2686.             /* Begin critical section type thing */
  2687.             Forbid(); Disable();
  2688.             
  2689.             /* Grab buffer info */
  2690.             pubData   = pubBulkSamplePacket;
  2691.             ulDataLen = ulSampleArraySize;
  2692.             IntData.ulByteSum = IntData.ulSaveByteSum = ulBulkSamplePacketSum;
  2693.             
  2694.             /* And don't let this buffer get sent again */
  2695.             pubBulkSamplePacket   = NULL;
  2696.             ulBulkSamplePacketSum = SILENCE;    /* silent */
  2697.  
  2698.             /* OK to continue multitasking now */
  2699.             Enable(); Permit();
  2700.  
  2701.             if (pubData) TransmitData(pubData, ulDataLen, ubCurrComp);
  2702.         }
  2703.  
  2704.         if (signal & SIGBREAKF_CTRL_D)
  2705.         {    
  2706.             ToggleMicButton(CODE_OFF);
  2707.             if (ubSamplerType == SAMPLER_TOCCATA) SetWindowTitle("Toccata sampling error?");
  2708.                              else printf("(Received CTRL_D)\n");
  2709.         }
  2710.         
  2711.         if (signal & (1L << SoundTaskPort->mp_SigBit)) 
  2712.         {
  2713.             HandleSoundPort(TRUE);
  2714.             SetMenuValues();
  2715.         }
  2716.  
  2717.         if (signal & (1L << PhonePort->mp_SigBit))
  2718.         {
  2719.             while (DMessage = GetMsg(PhonePort))
  2720.             {
  2721.                 switch(((struct AmiPhoneInfo *) DMessage)->ubControl)
  2722.                 {
  2723.                     case MSG_CONTROL_HI:    daemonInfo = (struct AmiPhoneInfo *) DMessage;
  2724.                                 daemonInfo->nPri = nReceivePri;        /* tell AmiPhoned what pri we want it at */
  2725.                                 SetMenuValues();
  2726.                                 break;
  2727.                                     
  2728.                     case MSG_CONTROL_BYE:    daemonInfo = &defMsg;    /* No more packets to listen to, go back to fake data */
  2729.                                 ClosePhoneSocket();     /* close off our end of the deal */
  2730.                                 AddPhonePort(FALSE);
  2731.                                 SetMenuValues();
  2732.                                 break;
  2733.                                 
  2734.                     case MSG_CONTROL_RELEASE:  if (BTransmitting == TRUE) ToggleMicButton(CODE_OFF);
  2735.                                    break;
  2736.                     
  2737.                     case MSG_CONTROL_UPDATE: SetMenuValues();
  2738.                                  break;
  2739.                                  
  2740.                     default: 
  2741.                         printf("Heard invalid message!!!\n");
  2742.                         break;
  2743.                 }
  2744.                 ReplyMsg(DMessage);
  2745.             }
  2746.         }
  2747.  
  2748.         if (signal & SIGBREAKF_CTRL_C) BProgramDone = TRUE;
  2749.  
  2750.         if (signal & (1<<GraphicTimerMP->mp_SigBit)) 
  2751.         {
  2752.             if (nToggleMode == TOGGLE_HOLD)
  2753.             {
  2754.                 if (BButtonHeld == FALSE) ToggleMicButton(CODE_OFF);
  2755.                 if (BSpaceTapped == TRUE) BSpaceTapped = BButtonHeld = FALSE;
  2756.             }
  2757.             
  2758.             /* Blank the volume-o-meter if we're not transmitting */
  2759.             if (BTransmitting == FALSE) ulLastVolume = SILENCE;
  2760.             UpdateReceiveDisplays();
  2761.             GTIMERGO;            
  2762.         }
  2763.  
  2764.         if ((rexxHost)&&(signal & (1L << rexxHost->port->mp_SigBit)))
  2765.         {
  2766.             ARexxDispatch(rexxHost);
  2767.             SetMenuValues();
  2768.         }
  2769.         
  2770.         if ((AppWindowPort)&&(signal & (1L << AppWindowPort->mp_SigBit))) HandleAppWindow();
  2771.         if (signal & (1L << PhoneWindow->UserPort->mp_SigBit)) HandleIDCMP(NULL);
  2772.         
  2773.     }
  2774.     EXIT("OK",RETURN_OK);
  2775. }
  2776.